create-bubbles 0.1.22 → 0.1.24
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/dist/index.mjs +5 -0
- package/index.js +1 -1
- package/package.json +25 -24
- package/template-taro-react-oxc/.env.development +1 -1
- package/template-taro-react-oxc/.env.production +1 -1
- package/template-taro-react-oxc/project.config.json +1 -1
- package/template-taro-vue-eslint/project.config.json +2 -2
- package/{template-vp-monorepo-react-nestjs → template-vp-monorepo-react-hono}/.spaces/server//347/231/273/345/275/225/JWT/344/270/216RefreshToken/350/275/256/346/215/242/351/211/264/346/235/203/346/236/266/346/236/204/345/256/236/347/216/260/346/214/207/345/215/227.md +588 -1133
- package/template-vp-monorepo-react-hono/.vite-hooks/commit-msg +2 -0
- package/template-vp-monorepo-react-hono/.vite-hooks/pre-commit +2 -0
- package/template-vp-monorepo-react-hono/.vscode/extensions.json +3 -0
- package/template-vp-monorepo-react-hono/.vscode/settings.json +23 -0
- package/template-vp-monorepo-react-hono/AGENTS.md +16 -0
- package/template-vp-monorepo-react-hono/README.md +54 -0
- package/template-vp-monorepo-react-hono/apps/server/.env.example +13 -0
- package/template-vp-monorepo-react-hono/apps/server/README.md +75 -0
- package/template-vp-monorepo-react-hono/apps/server/drizzle/0000_flaky_madame_masque.sql +18 -0
- package/template-vp-monorepo-react-hono/apps/server/drizzle/meta/0000_snapshot.json +153 -0
- package/template-vp-monorepo-react-hono/apps/server/drizzle/meta/_journal.json +13 -0
- package/template-vp-monorepo-react-hono/apps/server/drizzle.config.ts +19 -0
- package/template-vp-monorepo-react-hono/apps/server/package.json +46 -0
- package/template-vp-monorepo-react-hono/apps/server/src/app.test.ts +57 -0
- package/template-vp-monorepo-react-hono/apps/server/src/app.ts +68 -0
- package/template-vp-monorepo-react-hono/apps/server/src/common/errors/app-error.ts +23 -0
- package/template-vp-monorepo-react-hono/apps/server/src/common/http/response.ts +21 -0
- package/template-vp-monorepo-react-hono/apps/server/src/common/logger.ts +30 -0
- package/template-vp-monorepo-react-hono/apps/server/src/config/env.ts +54 -0
- package/template-vp-monorepo-react-hono/apps/server/src/index.bun.ts +60 -0
- package/template-vp-monorepo-react-hono/apps/server/src/index.ts +73 -0
- package/template-vp-monorepo-react-hono/apps/server/src/infrastructure/database/client.ts +46 -0
- package/template-vp-monorepo-react-hono/apps/server/src/infrastructure/database/schema/index.ts +1 -0
- package/template-vp-monorepo-react-hono/apps/server/src/infrastructure/database/schema/job-runs.ts +42 -0
- package/template-vp-monorepo-react-hono/apps/server/src/infrastructure/queue/connection.ts +6 -0
- package/template-vp-monorepo-react-hono/apps/server/src/infrastructure/redis/client.ts +39 -0
- package/template-vp-monorepo-react-hono/apps/server/src/infrastructure/redis/options.ts +28 -0
- package/template-vp-monorepo-react-hono/apps/server/src/modules/health/health.routes.ts +17 -0
- package/template-vp-monorepo-react-hono/apps/server/src/modules/health/health.service.ts +59 -0
- package/template-vp-monorepo-react-hono/apps/server/src/modules/jobs/jobs.queue.ts +46 -0
- package/template-vp-monorepo-react-hono/apps/server/src/modules/jobs/jobs.repository.ts +101 -0
- package/template-vp-monorepo-react-hono/apps/server/src/modules/jobs/jobs.routes.ts +46 -0
- package/template-vp-monorepo-react-hono/apps/server/src/modules/jobs/jobs.schemas.ts +9 -0
- package/template-vp-monorepo-react-hono/apps/server/src/modules/jobs/jobs.service.ts +57 -0
- package/template-vp-monorepo-react-hono/apps/server/src/modules/jobs/jobs.types.ts +11 -0
- package/template-vp-monorepo-react-hono/apps/server/src/modules/jobs/jobs.worker.ts +108 -0
- package/template-vp-monorepo-react-hono/apps/server/src/runtime/shutdown.ts +38 -0
- package/template-vp-monorepo-react-hono/apps/server/src/worker.ts +48 -0
- package/template-vp-monorepo-react-hono/apps/server/tsconfig.json +15 -0
- package/template-vp-monorepo-react-hono/apps/server/vite.config.ts +15 -0
- package/template-vp-monorepo-react-hono/apps/web/.env +2 -0
- package/template-vp-monorepo-react-hono/apps/web/.env.dev +1 -0
- package/template-vp-monorepo-react-hono/apps/web/.env.prod +1 -0
- package/template-vp-monorepo-react-hono/apps/web/index.html +13 -0
- package/template-vp-monorepo-react-hono/apps/web/package.json +35 -0
- package/template-vp-monorepo-react-hono/apps/web/public/favicon.svg +1 -0
- package/template-vp-monorepo-react-hono/apps/web/public/icons.svg +24 -0
- package/template-vp-monorepo-react-hono/apps/web/src/App.tsx +25 -0
- package/template-vp-monorepo-react-hono/apps/web/src/assets/hero.png +0 -0
- package/template-vp-monorepo-react-hono/apps/web/src/assets/react.svg +1 -0
- package/template-vp-monorepo-react-hono/apps/web/src/assets/vite.svg +1 -0
- package/template-vp-monorepo-react-hono/apps/web/src/components/Loading/PageLoading.tsx +11 -0
- package/template-vp-monorepo-react-hono/apps/web/src/locales/en_US.json +4 -0
- package/template-vp-monorepo-react-hono/apps/web/src/locales/zh_CN.json +4 -0
- package/template-vp-monorepo-react-hono/apps/web/src/main.tsx +5 -0
- package/template-vp-monorepo-react-hono/apps/web/src/pages/home/index.tsx +47 -0
- package/template-vp-monorepo-react-hono/apps/web/src/router/index.tsx +25 -0
- package/template-vp-monorepo-react-hono/apps/web/src/router/modules/.gitkeep +0 -0
- package/template-vp-monorepo-react-hono/apps/web/src/styles/index.css +7 -0
- package/template-vp-monorepo-react-hono/apps/web/src/types/auto-imports.d.ts +58 -0
- package/template-vp-monorepo-react-hono/apps/web/src/utils/env/index.ts +6 -0
- package/template-vp-monorepo-react-hono/apps/web/src/utils/request/core/index.ts +420 -0
- package/template-vp-monorepo-react-hono/apps/web/src/utils/request/core/utils.ts +39 -0
- package/template-vp-monorepo-react-hono/apps/web/src/utils/request/index.ts +61 -0
- package/template-vp-monorepo-react-hono/apps/web/tsconfig.json +18 -0
- package/template-vp-monorepo-react-hono/apps/web/vite.config.ts +45 -0
- package/template-vp-monorepo-react-hono/commitlint.config.js +1 -0
- package/template-vp-monorepo-react-hono/docker-compose.yml +41 -0
- package/template-vp-monorepo-react-hono/mise.toml +4 -0
- package/template-vp-monorepo-react-hono/package.json +37 -0
- package/template-vp-monorepo-react-hono/packages/i18n/core/package.json +20 -0
- package/template-vp-monorepo-react-hono/packages/i18n/core/src/format.ts +9 -0
- package/template-vp-monorepo-react-hono/packages/i18n/core/src/i18n.ts +73 -0
- package/template-vp-monorepo-react-hono/packages/i18n/core/src/index.ts +24 -0
- package/template-vp-monorepo-react-hono/packages/i18n/core/src/storage.ts +47 -0
- package/template-vp-monorepo-react-hono/packages/i18n/core/src/store.ts +48 -0
- package/template-vp-monorepo-react-hono/packages/i18n/core/src/types.ts +36 -0
- package/template-vp-monorepo-react-hono/packages/i18n/core/tsconfig.json +4 -0
- package/template-vp-monorepo-react-hono/packages/i18n/core/vite.config.ts +13 -0
- package/template-vp-monorepo-react-hono/packages/i18n/react/package.json +28 -0
- package/template-vp-monorepo-react-hono/packages/i18n/react/src/index.tsx +26 -0
- package/template-vp-monorepo-react-hono/packages/i18n/react/src/use-store.ts +14 -0
- package/template-vp-monorepo-react-hono/packages/i18n/react/tsconfig.json +9 -0
- package/template-vp-monorepo-react-hono/packages/i18n/react/vite.config.ts +16 -0
- package/template-vp-monorepo-react-hono/packages/i18n/vue/package.json +27 -0
- package/template-vp-monorepo-react-hono/packages/i18n/vue/src/index.ts +52 -0
- package/template-vp-monorepo-react-hono/packages/i18n/vue/src/use-store.ts +19 -0
- package/template-vp-monorepo-react-hono/packages/i18n/vue/tsconfig.json +8 -0
- package/template-vp-monorepo-react-hono/packages/i18n/vue/vite.config.ts +16 -0
- package/template-vp-monorepo-react-hono/pnpm-workspace.yaml +57 -0
- package/template-vp-monorepo-react-hono/scripts/clean.mjs +48 -0
- package/template-vp-monorepo-react-hono/tsconfig.base.json +10 -0
- package/template-vp-monorepo-react-hono/tsconfig.bundler.json +12 -0
- package/template-vp-monorepo-react-hono/tsconfig.json +11 -0
- package/template-vp-monorepo-react-hono/tsconfig.lib.json +10 -0
- package/template-vp-monorepo-react-hono/vite.config.ts +20 -0
- package/template-vp-monorepo-react-nestjs/.spaces/server/todo.md +991 -0
- package/template-vp-monorepo-react-nestjs/.vscode/launch.json +16 -0
- package/template-vp-monorepo-react-nestjs/.vscode/settings.json +21 -17
- package/template-vp-monorepo-react-nestjs/apps/server/.env.development +3 -39
- package/template-vp-monorepo-react-nestjs/apps/server/.swcrc +8 -0
- package/template-vp-monorepo-react-nestjs/apps/server/drizzle.config.ts +8 -3
- package/template-vp-monorepo-react-nestjs/apps/server/nest-cli.json +8 -1
- package/template-vp-monorepo-react-nestjs/apps/server/package.json +11 -6
- package/template-vp-monorepo-react-nestjs/apps/server/src/app.controller.ts +2 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/app.module.ts +20 -15
- package/template-vp-monorepo-react-nestjs/apps/server/src/common/adapters/fastify.adapter.ts +16 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/common/constants/auth.ts +2 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/common/constants/response.ts +0 -4
- package/template-vp-monorepo-react-nestjs/apps/server/src/common/constants/session.constants.ts +28 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/common/decorators/current-auth.decorator.ts +16 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/common/decorators/public.decorator.ts +4 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/common/dto/api-failure.dto.ts +25 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/common/error/common.error.ts +40 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/common/exceptions/app.exception.ts +55 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/common/filters/global-exception.filter.ts +384 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/common/openapi/response-headers.ts +9 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/config/index.ts +1 -1
- package/template-vp-monorepo-react-nestjs/apps/server/src/config/session.config.ts +36 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/database/schema.ts +7 -8
- package/template-vp-monorepo-react-nestjs/apps/server/src/main.ts +29 -8
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/auth/auth.controller.ts +55 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/auth/auth.errors.ts +42 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/auth/auth.module.ts +26 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/auth/auth.repository.ts +40 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/auth/auth.service.ts +129 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/auth/dto/auth-repsponse.dto.ts +31 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/auth/dto/login.dto.ts +11 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/auth/dto/register.dto.ts +17 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/auth/guards/session-auth.guard.ts +50 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/auth/password.service.ts +24 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/auth/session/session-store.service.ts +198 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/auth/session/session-token.service.ts +29 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/auth/session/session.script.ts +221 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/auth/session/session.types.ts +24 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/test/db/db.controller.ts +1 -1
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/test/db/dto/create-user.dto.ts +3 -5
- package/template-vp-monorepo-react-nestjs/apps/server/src/modules/test/redis/redis.service.ts +1 -1
- package/template-vp-monorepo-react-nestjs/apps/server/src/utils/env-arr.ts +3 -0
- package/template-vp-monorepo-react-nestjs/apps/server/test/error-catalog.spec.ts +30 -0
- package/template-vp-monorepo-react-nestjs/apps/server/tsconfig.build.json +11 -1
- package/template-vp-monorepo-react-nestjs/apps/server/tsconfig.json +12 -20
- package/template-vp-monorepo-react-nestjs/apps/server/vite.config.ts +15 -0
- package/template-vp-monorepo-react-nestjs/apps/web/package.json +1 -0
- package/template-vp-monorepo-react-nestjs/apps/web/tsconfig.json +5 -15
- package/template-vp-monorepo-react-nestjs/apps/web-vue/commitlint.config.js +1 -1
- package/template-vp-monorepo-react-nestjs/apps/web-vue/lefthook.yml +1 -1
- package/template-vp-monorepo-react-nestjs/apps/web-vue/package.json +1 -3
- package/template-vp-monorepo-react-nestjs/apps/web-vue/src/api/index.ts +5 -5
- package/template-vp-monorepo-react-nestjs/apps/web-vue/src/components/Icon/svg-icon.vue +3 -3
- package/template-vp-monorepo-react-nestjs/apps/web-vue/src/hooks/chart/lib.ts +6 -6
- package/template-vp-monorepo-react-nestjs/apps/web-vue/src/hooks/chart/useEcharts.ts +34 -29
- package/template-vp-monorepo-react-nestjs/apps/web-vue/src/i18n/instance.ts +2 -0
- package/template-vp-monorepo-react-nestjs/apps/web-vue/src/layout/default/index.vue +17 -32
- package/template-vp-monorepo-react-nestjs/apps/web-vue/src/locales/en_US.json +4 -1
- package/template-vp-monorepo-react-nestjs/apps/web-vue/src/locales/zh_CN.json +4 -1
- package/template-vp-monorepo-react-nestjs/apps/web-vue/src/router/guard/index.ts +3 -3
- package/template-vp-monorepo-react-nestjs/apps/web-vue/src/router/guard/permissionGuard.ts +7 -7
- package/template-vp-monorepo-react-nestjs/apps/web-vue/src/router/index.ts +7 -7
- package/template-vp-monorepo-react-nestjs/apps/web-vue/src/router/interface.ts +6 -6
- package/template-vp-monorepo-react-nestjs/apps/web-vue/src/store/index.ts +6 -6
- package/template-vp-monorepo-react-nestjs/apps/web-vue/src/store/modules/user.ts +9 -9
- package/template-vp-monorepo-react-nestjs/apps/web-vue/src/styles/index.scss +3 -3
- package/template-vp-monorepo-react-nestjs/apps/web-vue/src/types/antdv-next.d.ts +1 -0
- package/template-vp-monorepo-react-nestjs/apps/web-vue/src/utils/env.ts +1 -1
- package/template-vp-monorepo-react-nestjs/apps/web-vue/src/utils/request/core/index.ts +63 -45
- package/template-vp-monorepo-react-nestjs/apps/web-vue/src/utils/request/core/utils.ts +12 -6
- package/template-vp-monorepo-react-nestjs/apps/web-vue/src/utils/request/index.ts +1 -1
- package/template-vp-monorepo-react-nestjs/apps/web-vue/src/views/example/echart/config.ts +687 -687
- package/template-vp-monorepo-react-nestjs/apps/web-vue/src/views/example/echart/index.vue +7 -7
- package/template-vp-monorepo-react-nestjs/apps/web-vue/src/views/example/tree-chart.vue +2 -7
- package/template-vp-monorepo-react-nestjs/apps/web-vue/src/views/home/index.vue +13 -3
- package/template-vp-monorepo-react-nestjs/apps/web-vue/tsconfig.json +5 -17
- package/template-vp-monorepo-react-nestjs/apps/web-vue/uno.config.ts +5 -5
- package/template-vp-monorepo-react-nestjs/i18n.config.ts +22 -0
- package/template-vp-monorepo-react-nestjs/package.json +12 -1
- package/template-vp-monorepo-react-nestjs/packages/i18n/cli/README.md +113 -0
- package/template-vp-monorepo-react-nestjs/packages/i18n/cli/docs/excel-sync-plan.md +618 -0
- package/template-vp-monorepo-react-nestjs/packages/i18n/cli/package.json +31 -0
- package/template-vp-monorepo-react-nestjs/packages/i18n/cli/src/cli.ts +5 -0
- package/template-vp-monorepo-react-nestjs/packages/i18n/cli/src/command.ts +512 -0
- package/template-vp-monorepo-react-nestjs/packages/i18n/cli/src/config.ts +15 -0
- package/template-vp-monorepo-react-nestjs/packages/i18n/cli/src/files.ts +67 -0
- package/template-vp-monorepo-react-nestjs/packages/i18n/cli/src/index.ts +19 -0
- package/template-vp-monorepo-react-nestjs/packages/i18n/cli/src/load-config.ts +228 -0
- package/template-vp-monorepo-react-nestjs/packages/i18n/cli/src/report.ts +57 -0
- package/template-vp-monorepo-react-nestjs/packages/i18n/cli/src/scanner.test.ts +81 -0
- package/template-vp-monorepo-react-nestjs/packages/i18n/cli/src/scanner.ts +290 -0
- package/template-vp-monorepo-react-nestjs/packages/i18n/cli/src/sync.ts +274 -0
- package/template-vp-monorepo-react-nestjs/packages/i18n/cli/test/command.test.ts +209 -0
- package/template-vp-monorepo-react-nestjs/packages/i18n/cli/test/config.test.ts +19 -0
- package/template-vp-monorepo-react-nestjs/packages/i18n/cli/test/load-config.test.ts +194 -0
- package/template-vp-monorepo-react-nestjs/packages/i18n/cli/test/report.test.ts +63 -0
- package/template-vp-monorepo-react-nestjs/packages/i18n/cli/test/sync.test.ts +203 -0
- package/template-vp-monorepo-react-nestjs/packages/i18n/cli/test/temporary-directory.ts +25 -0
- package/template-vp-monorepo-react-nestjs/packages/i18n/cli/tsconfig.json +9 -0
- package/template-vp-monorepo-react-nestjs/packages/i18n/cli/vite.config.ts +18 -0
- package/template-vp-monorepo-react-nestjs/packages/i18n/core/tsconfig.json +1 -12
- package/template-vp-monorepo-react-nestjs/packages/i18n/react/tsconfig.json +3 -10
- package/template-vp-monorepo-react-nestjs/packages/i18n/vue/tsconfig.json +3 -10
- package/template-vp-monorepo-react-nestjs/packages/shared/package.json +40 -0
- package/template-vp-monorepo-react-nestjs/packages/shared/src/index.ts +13 -0
- package/template-vp-monorepo-react-nestjs/packages/shared/src/types/auth.ts +35 -0
- package/template-vp-monorepo-react-nestjs/packages/shared/src/types/common.ts +11 -0
- package/template-vp-monorepo-react-nestjs/packages/shared/src/types/index.ts +11 -0
- package/template-vp-monorepo-react-nestjs/packages/shared/src/utils/account.ts +5 -0
- package/template-vp-monorepo-react-nestjs/packages/shared/src/utils/index.ts +2 -0
- package/template-vp-monorepo-react-nestjs/packages/shared/src/utils/session-terminal.ts +11 -0
- package/template-vp-monorepo-react-nestjs/packages/shared/tsconfig.json +4 -0
- package/template-vp-monorepo-react-nestjs/packages/shared/vite.config.ts +17 -0
- package/template-vp-monorepo-react-nestjs/pnpm-workspace.yaml +6 -6
- package/template-vp-monorepo-react-nestjs/scripts/clean.mjs +48 -0
- package/template-vp-monorepo-react-nestjs/tsconfig.base.json +10 -0
- package/template-vp-monorepo-react-nestjs/tsconfig.bundler.json +12 -0
- package/template-vp-monorepo-react-nestjs/tsconfig.json +8 -6
- package/template-vp-monorepo-react-nestjs/tsconfig.lib.json +10 -0
- package/template-vp-monorepo-react-nestjs/vite.config.ts +2 -1
- package/template-vp-vue-eslint-vapor/.env +6 -0
- package/template-vp-vue-eslint-vapor/.env.development +2 -0
- package/template-vp-vue-eslint-vapor/.env.production +2 -0
- package/template-vp-vue-eslint-vapor/.vite-hooks/commit-msg +1 -0
- package/template-vp-vue-eslint-vapor/.vite-hooks/pre-commit +1 -0
- package/template-vp-vue-eslint-vapor/.vscode/extensions.json +3 -0
- package/template-vp-vue-eslint-vapor/AGENTS.md +16 -0
- package/template-vp-vue-eslint-vapor/README.md +93 -0
- package/template-vp-vue-eslint-vapor/commitlint.config.js +1 -0
- package/template-vp-vue-eslint-vapor/eslint.config.js +13 -0
- package/template-vp-vue-eslint-vapor/index.html +13 -0
- package/template-vp-vue-eslint-vapor/package.json +64 -0
- package/template-vp-vue-eslint-vapor/pnpm-workspace.yaml +2 -0
- package/template-vp-vue-eslint-vapor/public/vite.svg +1 -0
- package/template-vp-vue-eslint-vapor/src/App.vue +7 -0
- package/template-vp-vue-eslint-vapor/src/api/index.ts +12 -0
- package/template-vp-vue-eslint-vapor/src/assets/icon/home.svg +3 -0
- package/template-vp-vue-eslint-vapor/src/assets/icon/logo.svg +1 -0
- package/template-vp-vue-eslint-vapor/src/assets/image/.gitkeep +0 -0
- package/template-vp-vue-eslint-vapor/src/components/Icon/svg-icon.vue +29 -0
- package/template-vp-vue-eslint-vapor/src/hooks/chart/lib.ts +57 -0
- package/template-vp-vue-eslint-vapor/src/hooks/chart/useEcharts.ts +65 -0
- package/template-vp-vue-eslint-vapor/src/layout/default/header/index.vue +57 -0
- package/template-vp-vue-eslint-vapor/src/layout/default/index.vue +138 -0
- package/template-vp-vue-eslint-vapor/src/main.ts +19 -0
- package/template-vp-vue-eslint-vapor/src/router/guard/index.ts +7 -0
- package/template-vp-vue-eslint-vapor/src/router/guard/permissionGuard.ts +13 -0
- package/template-vp-vue-eslint-vapor/src/router/index.ts +18 -0
- package/template-vp-vue-eslint-vapor/src/router/interface.ts +9 -0
- package/template-vp-vue-eslint-vapor/src/router/modules/index.ts +33 -0
- package/template-vp-vue-eslint-vapor/src/store/index.ts +11 -0
- package/template-vp-vue-eslint-vapor/src/store/modules/user.ts +17 -0
- package/template-vp-vue-eslint-vapor/src/styles/font.scss +0 -0
- package/template-vp-vue-eslint-vapor/src/styles/index.scss +29 -0
- package/template-vp-vue-eslint-vapor/src/styles/variables.scss +3 -0
- package/template-vp-vue-eslint-vapor/src/types/vite-env.d.ts +15 -0
- package/template-vp-vue-eslint-vapor/src/utils/env.ts +11 -0
- package/template-vp-vue-eslint-vapor/src/utils/request/core/index.ts +425 -0
- package/template-vp-vue-eslint-vapor/src/utils/request/core/utils.ts +39 -0
- package/template-vp-vue-eslint-vapor/src/utils/request/index.ts +44 -0
- package/template-vp-vue-eslint-vapor/src/views/example/echart/config.ts +1794 -0
- package/template-vp-vue-eslint-vapor/src/views/example/echart/index.vue +20 -0
- package/template-vp-vue-eslint-vapor/src/views/example/tree-chart.vue +16 -0
- package/template-vp-vue-eslint-vapor/src/views/home/index.vue +16 -0
- package/template-vp-vue-eslint-vapor/src/views/login/index.vue +9 -0
- package/template-vp-vue-eslint-vapor/tsconfig.json +32 -0
- package/template-vp-vue-eslint-vapor/tsconfig.tsbuildinfo +1 -0
- package/template-vp-vue-eslint-vapor/uno.config.ts +17 -0
- package/template-vp-vue-eslint-vapor/vite.config.ts +66 -0
- package/template-vp-monorepo-react-nestjs/apps/server/src/common/constants/decorator.ts +0 -2
- package/template-vp-monorepo-react-nestjs/apps/server/src/common/decorators/bypass.ts +0 -12
- package/template-vp-monorepo-react-nestjs/apps/server/src/common/interceptors/transform.ts +0 -34
- package/template-vp-monorepo-react-nestjs/apps/server/src/common/model/response.ts +0 -23
- package/template-vp-monorepo-react-nestjs/apps/server/src/config/auth.config.ts +0 -64
- package/template-vp-monorepo-react-nestjs/apps/web-vue/pnpm-workspace.yaml +0 -16
- /package/{template-vp-monorepo-react-nestjs/apps/server/src/config/security.config.ts → template-vp-monorepo-react-hono/.agents/auth.config.ts} +0 -0
|
@@ -0,0 +1,991 @@
|
|
|
1
|
+
# Server 未完成事项与改造路线图
|
|
2
|
+
|
|
3
|
+
> 审计日期:2026-08-18
|
|
4
|
+
> 审计对象:当前仓库的 apps/server 实际源码,而不是文档中计划实现的代码。
|
|
5
|
+
> 对照项目:buqiyuan/nest-admin、linlingqin77/Nest-Admin-Soybean,以及当前项目已有的异常处理与 Session 设计文档。
|
|
6
|
+
|
|
7
|
+
## 0. 先给结论
|
|
8
|
+
|
|
9
|
+
当前 Server 不是完整的管理后台后端,而是一个具备以下能力的开发模板:
|
|
10
|
+
|
|
11
|
+
- NestJS 11 + Fastify。
|
|
12
|
+
- PostgreSQL + Drizzle ORM。
|
|
13
|
+
- Redis。
|
|
14
|
+
- Zod 请求 DTO、Swagger。
|
|
15
|
+
- 用户注册、登录、退出、获取当前用户。
|
|
16
|
+
- Argon2id 密码哈希。
|
|
17
|
+
- Opaque Bearer Token + Redis Session 的基础设计。
|
|
18
|
+
- 全局 Session 认证 Guard。
|
|
19
|
+
|
|
20
|
+
但目前距离可安全部署仍有明显差距,而且有几项不是“以后再增强”,而是会直接导致认证不可用、敏感数据暴露或生产无法启动的阻断问题。
|
|
21
|
+
|
|
22
|
+
最先处理的顺序必须是:
|
|
23
|
+
|
|
24
|
+
1. 移除运行时 DB/Redis 测试接口。
|
|
25
|
+
2. 修复 Redis Session 的四个 Lua 错误并补真实 Redis 测试。
|
|
26
|
+
3. 轮换已提交的密钥,建立正确的环境变量管理方式。
|
|
27
|
+
4. 修复生产依赖、迁移文件和生产启动命令。
|
|
28
|
+
5. 按现有异常处理指南落地统一错误协议。
|
|
29
|
+
6. 加入登录限流、抗账号枚举和最小授权模型。
|
|
30
|
+
7. 再建设用户、角色、菜单、审计、文件、任务等管理后台模块。
|
|
31
|
+
|
|
32
|
+
异常处理的完整施工步骤不在本文件重复,请直接执行:
|
|
33
|
+
|
|
34
|
+
[NestJS 11 全链路统一错误处理改造指南](../server/登录/04.exception.md)
|
|
35
|
+
|
|
36
|
+
## 1. 优先级定义
|
|
37
|
+
|
|
38
|
+
| 优先级 | 含义 |
|
|
39
|
+
| ------ | ------------------------------------------------------ |
|
|
40
|
+
| P0 | 当前存在运行时错误、安全暴露或发布阻断;完成前不要上线 |
|
|
41
|
+
| P1 | 第一套测试环境或生产环境前必须具备的后端基线 |
|
|
42
|
+
| P2 | 成为完整管理后台所需要的业务与平台能力 |
|
|
43
|
+
| P3 | 规模扩大、合规或明确产品需求出现后再实施 |
|
|
44
|
+
|
|
45
|
+
## 2. 当前能力对照
|
|
46
|
+
|
|
47
|
+
| 能力 | 当前状态 | 判断 |
|
|
48
|
+
| ---------------------- | ------------------------ | ----------------------------------------- |
|
|
49
|
+
| NestJS + Fastify 启动 | 已有 | 可保留 |
|
|
50
|
+
| PostgreSQL + Drizzle | 部分完成 | 缺迁移版本控制、连接池生命周期和生产参数 |
|
|
51
|
+
| Redis Session | 设计已有但当前被错误阻断 | Lua 脚本必须先修 |
|
|
52
|
+
| Argon2id 密码 | 已有 | 缺参数版本、rehash、抗枚举与限流 |
|
|
53
|
+
| Zod 请求校验 | 已有 | 缺统一 validation 错误协议 |
|
|
54
|
+
| Zod 响应防泄漏 | 名义存在 | 没有任何运行时响应 schema,实际未形成保护 |
|
|
55
|
+
| Swagger | 部分完成 | 永久公开,缺响应与错误契约 |
|
|
56
|
+
| 统一异常处理 | 未实现 | 仅成功响应被包装 |
|
|
57
|
+
| requestId 与结构化日志 | 未实现 | 无请求关联、统一脱敏和访问日志 |
|
|
58
|
+
| 自动化 Server 测试 | 未实现 | 现有 modules/test 是运行时接口,不是测试 |
|
|
59
|
+
| RBAC 与资源授权 | 未实现 | 所有登录用户权限相同 |
|
|
60
|
+
| 用户管理后台 | 未实现 | 只有注册、登录、me、logout |
|
|
61
|
+
| 菜单、角色、部门、公司 | 未实现 | 数据表与 API 均不存在 |
|
|
62
|
+
| 审计、登录日志 | 未实现 | 无安全事件记录 |
|
|
63
|
+
| 健康检查与优雅停机 | 未实现 | 无 live/ready,也没有关闭数据库连接池 |
|
|
64
|
+
| 文件上传与 MinIO | 未实现 | Compose 有 MinIO,但 Server 没有任何接入 |
|
|
65
|
+
| 队列与定时任务 | 未实现 | 无 Bull、Schedule、Worker 或失败治理 |
|
|
66
|
+
| 生产镜像与 CI/CD | 未实现 | 无 Server Dockerfile 和流水线 |
|
|
67
|
+
|
|
68
|
+
### 2.1 从两个参考项目分别借鉴什么
|
|
69
|
+
|
|
70
|
+
| 参考项目 | 值得借鉴 | 当前项目应该怎样吸收 |
|
|
71
|
+
| ------------------- | --------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
72
|
+
| buqiyuan/nest-admin | 管理后台模块拆分、用户/角色/权限/菜单、任务、日志、文件等成熟功能边界 | 借鉴模块和权限模型,不复制 HTTP 200 业务错误、字符串 split、Filter 内进程监听器 |
|
|
73
|
+
| Nest-Admin-Soybean | 错误码目录与文档、requestId、结构化日志和脱敏、登录安全、租户与可观测性模块、较完整测试 | 先吸收错误契约、日志、安全测试和模块边界;租户、MFA、OTel 等按产品需要实施,不复制错误返回 200、开发环境返回 stack、信任客户端 requestId 或过晚启动 OTel |
|
|
74
|
+
|
|
75
|
+
本文件不是要求把两个仓库的全部模块复制过来,而是把当前项目真正缺失的能力分成“阻断项、生产基线、管理后台能力、可选扩展”四层。
|
|
76
|
+
|
|
77
|
+
### 2.2 参考证据与建议边界
|
|
78
|
+
|
|
79
|
+
本次核对固定在以下提交:
|
|
80
|
+
|
|
81
|
+
- nest-admin:2eeccc4cb699d1aedbe04b4437a9d095cde02c74。
|
|
82
|
+
- Nest-Admin-Soybean:83a83f72189565e4eff3f2ca074f558d82e907e5。
|
|
83
|
+
- Soybean 异常体系重构提交:866475d374c31b4b317f41089da40abd2e13dbfd。
|
|
84
|
+
|
|
85
|
+
可直接审计的核心文件:
|
|
86
|
+
|
|
87
|
+
- [nest-admin 全局 Filter](https://github.com/buqiyuan/nest-admin/blob/2eeccc4cb699d1aedbe04b4437a9d095cde02c74/src/common/filters/any-exception.filter.ts)
|
|
88
|
+
- [nest-admin BusinessException](https://github.com/buqiyuan/nest-admin/blob/2eeccc4cb699d1aedbe04b4437a9d095cde02c74/src/common/exceptions/biz.exception.ts)
|
|
89
|
+
- [nest-admin 错误码](https://github.com/buqiyuan/nest-admin/blob/2eeccc4cb699d1aedbe04b4437a9d095cde02c74/src/constants/error-code.constant.ts)
|
|
90
|
+
- [Soybean 全局 Filter](https://github.com/linlingqin77/Nest-Admin-Soybean/blob/83a83f72189565e4eff3f2ca074f558d82e907e5/apps/server/src/core/filters/global-exception.filter.ts)
|
|
91
|
+
- [Soybean requestId middleware](https://github.com/linlingqin77/Nest-Admin-Soybean/blob/83a83f72189565e4eff3f2ca074f558d82e907e5/apps/server/src/core/middleware/request-id.middleware.ts)
|
|
92
|
+
- [Soybean BusinessException](https://github.com/linlingqin77/Nest-Admin-Soybean/blob/83a83f72189565e4eff3f2ca074f558d82e907e5/apps/server/src/shared/exceptions/business.exception.ts)
|
|
93
|
+
- [Soybean 错误码文档生成](https://github.com/linlingqin77/Nest-Admin-Soybean/blob/83a83f72189565e4eff3f2ca074f558d82e907e5/apps/server/src/shared/response/error-codes.doc.ts)
|
|
94
|
+
- [Soybean Pino 配置](https://github.com/linlingqin77/Nest-Admin-Soybean/blob/83a83f72189565e4eff3f2ca074f558d82e907e5/apps/server/src/infrastructure/logging/pino-logger.config.ts)
|
|
95
|
+
- [Soybean CLS 上下文](https://github.com/linlingqin77/Nest-Admin-Soybean/blob/83a83f72189565e4eff3f2ca074f558d82e907e5/apps/server/src/tenant/context/cls.module.ts)
|
|
96
|
+
- [Soybean tracing 初始化](https://github.com/linlingqin77/Nest-Admin-Soybean/blob/83a83f72189565e4eff3f2ca074f558d82e907e5/apps/server/src/observability/tracing/tracing.service.ts)
|
|
97
|
+
- [Soybean 慢查询扩展](https://github.com/linlingqin77/Nest-Admin-Soybean/blob/83a83f72189565e4eff3f2ca074f558d82e907e5/apps/server/src/infrastructure/prisma/slow-query.extension.ts)
|
|
98
|
+
|
|
99
|
+
P0 和 P1 的“当前问题”均来自本仓库源码。乐观锁、病毒扫描、供应商切换、Passkey、SAML、Outbox 等属于额外的现代化建议,本文件不声称两个参考仓库已经完整实现它们。
|
|
100
|
+
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
# P0:上线前阻断项
|
|
104
|
+
|
|
105
|
+
## S0-01 修复 Redis Session Lua 脚本
|
|
106
|
+
|
|
107
|
+
### 当前问题
|
|
108
|
+
|
|
109
|
+
文件:
|
|
110
|
+
|
|
111
|
+
- apps/server/src/modules/auth/session/session.script.ts
|
|
112
|
+
- apps/server/src/modules/auth/session/session-store.service.ts
|
|
113
|
+
|
|
114
|
+
已确认存在四个独立错误:
|
|
115
|
+
|
|
116
|
+
1. 验证脚本使用了未定义的 idleTtlMS,而正确变量是 idleTtlMs。
|
|
117
|
+
有效 Token 进入 Lua 后会尝试比较 nil 和数字,最终被转换成 503。
|
|
118
|
+
2. Session 不存在时返回 NOT_FUND,但 TypeScript 只识别 NOT_FOUND。
|
|
119
|
+
即使修正上一项,正常的无效 Session 仍会被误判成 Redis 服务故障。
|
|
120
|
+
3. 创建脚本使用了未定义、也没有通过 ARGV 传入的 sessionKeyPrefix。
|
|
121
|
+
同一终端第二次登录、准备删除旧 Session 时会报错。
|
|
122
|
+
4. revoke 脚本把 Lua 关键字 do 写成了大写 DO。
|
|
123
|
+
revokeAllForUser 一旦被调用,脚本会出现语法错误。
|
|
124
|
+
|
|
125
|
+
创建脚本在报错前已经执行了 HSET、SET 等写操作。Redis Lua 的执行具有原子隔离,但脚本错误不会自动回滚之前已经执行的写操作,因此可能出现“接口返回失败,但部分新会话数据已经写入”的状态。
|
|
126
|
+
|
|
127
|
+
### TODO
|
|
128
|
+
|
|
129
|
+
- [ ] 将 idleTtlMS 统一修正为 idleTtlMs。
|
|
130
|
+
- [ ] 将 NOT_FUND 统一修正为 NOT_FOUND。
|
|
131
|
+
- [ ] 为创建脚本显式传入 Session Key 前缀,或者重构参数使脚本不依赖未声明变量。
|
|
132
|
+
- [ ] 将 revoke 脚本中的 DO 改为 do。
|
|
133
|
+
- [ ] 把 Lua 返回码集中定义,避免 TypeScript 与 Lua 各写一份字符串。
|
|
134
|
+
- [ ] 删除 SessionStoreService 中 terminal: any,恢复 SessionTerminalType。
|
|
135
|
+
- [ ] 对脚本返回值增加严格长度和数字范围校验。
|
|
136
|
+
- [ ] 用真实 Redis 编写集成测试,不只测试字符串内容。
|
|
137
|
+
|
|
138
|
+
### 验收标准
|
|
139
|
+
|
|
140
|
+
- [ ] 首次登录成功。
|
|
141
|
+
- [ ] 同终端第二次登录成功,新 Token 有效,旧 Token 返回 401。
|
|
142
|
+
- [ ] 不同终端可以同时在线。
|
|
143
|
+
- [ ] 有效 Token 可以 validate 并滑动续期。
|
|
144
|
+
- [ ] 不存在、已替换、空闲过期、绝对过期的 Session 返回 401,而不是 503。
|
|
145
|
+
- [ ] Redis 不可用时返回 503。
|
|
146
|
+
- [ ] logout 不会删除同终端后来创建的新 Session。
|
|
147
|
+
- [ ] revokeAllForUser 可以撤销所有终端。
|
|
148
|
+
- [ ] 并发测试结束后,每个 Slot 指向的 digest 都有对应 Session Hash,每个有效 Session 也由正确 Slot 引用;不存在单边孤儿 Key。
|
|
149
|
+
|
|
150
|
+
## S0-02 移除生产运行时的 DB/Redis 测试接口
|
|
151
|
+
|
|
152
|
+
### 当前问题
|
|
153
|
+
|
|
154
|
+
AppModule 无条件导入:
|
|
155
|
+
|
|
156
|
+
- TestDbModule
|
|
157
|
+
- TestRedisModule
|
|
158
|
+
|
|
159
|
+
这两个模块不是自动化测试,而是真实运行的 HTTP Controller。
|
|
160
|
+
|
|
161
|
+
风险包括:
|
|
162
|
+
|
|
163
|
+
- GET /db/users 查询完整 users 行,会返回 passwordHash。
|
|
164
|
+
- POST /db/user 绕过 AuthService、PasswordService 和账号规范化,直接写数据库。
|
|
165
|
+
- POST /redis/set 可以修改任意 Redis Key。
|
|
166
|
+
- GET /redis/get 可以尝试读取任意 Redis Key。
|
|
167
|
+
- 系统没有 RBAC;任何通过公开注册得到账号的用户都拥有同样权限。
|
|
168
|
+
- Redis get 接口还把 @Query('key') 的字符串绑定给对象 DTO,接口本身存在参数绑定错误。
|
|
169
|
+
|
|
170
|
+
### TODO
|
|
171
|
+
|
|
172
|
+
- [ ] 从 AppModule 删除 TestDbModule 和 TestRedisModule。
|
|
173
|
+
- [ ] 删除这些运行时 Controller,或只在完全隔离的本地开发模块中启用。
|
|
174
|
+
- [ ] 不要用“已经登录”作为调试接口的安全边界。
|
|
175
|
+
- [ ] 数据库检查改为固定逻辑的 readiness probe。
|
|
176
|
+
- [ ] Redis 检查只执行固定 PING,不接受客户端提供 key、value 或 pattern。
|
|
177
|
+
- [ ] 全仓搜索任何返回 users 完整实体的接口。
|
|
178
|
+
- [ ] 为所有公开响应增加 passwordHash 永不出现的测试。
|
|
179
|
+
|
|
180
|
+
### 验收标准
|
|
181
|
+
|
|
182
|
+
- [ ] 生产路由中不存在 /db、/db/users、/db/user、/redis/set、/redis/get。
|
|
183
|
+
- [ ] 普通用户无法直接访问数据库或 Redis 调试能力。
|
|
184
|
+
- [ ] 任何响应、日志和 Swagger schema 都不包含 passwordHash。
|
|
185
|
+
|
|
186
|
+
## S0-03 处理已经提交的环境文件和密钥
|
|
187
|
+
|
|
188
|
+
### 当前问题
|
|
189
|
+
|
|
190
|
+
Git 当前跟踪:
|
|
191
|
+
|
|
192
|
+
- apps/server/.env.development
|
|
193
|
+
- apps/server/.env.production
|
|
194
|
+
|
|
195
|
+
其中包含已经赋值的数据库、Redis、JWT、LLM 等配置。无论这些值是不是当前生产值,都不应该把真实凭据长期放在仓库中。
|
|
196
|
+
|
|
197
|
+
另外:
|
|
198
|
+
|
|
199
|
+
- 当前认证已经采用 Redis Session,但环境文件仍保留 JWT_SECRET。
|
|
200
|
+
- session.config.ts 强制要求 SESSION_TOKEN_PEPPER。
|
|
201
|
+
- 仓库提供的 production 环境文件没有该变量;如果部署平台不额外注入,应用会启动失败。
|
|
202
|
+
|
|
203
|
+
### TODO
|
|
204
|
+
|
|
205
|
+
- [ ] 判断所有已提交值是否曾被真实环境使用。
|
|
206
|
+
- [ ] 只要无法证明是假值,就按泄露处理并立即轮换。
|
|
207
|
+
- [ ] 从 Git 跟踪中移除真实 .env.development 和 .env.production。
|
|
208
|
+
- [ ] 增加不含真实值的 .env.example。
|
|
209
|
+
- [ ] 生产密钥改由部署平台 Secret、Vault、KMS 或环境注入。
|
|
210
|
+
- [ ] 不要通过“把 SESSION_TOKEN_PEPPER 写进已跟踪 production 文件”修复启动问题。
|
|
211
|
+
- [ ] 删除已经不使用的 JWT_SECRET。
|
|
212
|
+
- [ ] 为 SESSION_TOKEN_PEPPER 建立轮换策略;轮换会让旧 Session 失效,需要明确发布行为。
|
|
213
|
+
- [ ] 如已提交真实密钥,评估是否需要清理 Git 历史。
|
|
214
|
+
- [ ] 在 CI 中运行选定的 secret scanner,并维护经过审查的 allowlist。
|
|
215
|
+
|
|
216
|
+
### 验收标准
|
|
217
|
+
|
|
218
|
+
- [ ] Git 不再跟踪任何真实数据库、Redis、LLM 或 Session 密钥。
|
|
219
|
+
- [ ] 新开发者可以从 .env.example 理解全部必需配置。
|
|
220
|
+
- [ ] 缺少必需变量时应用在启动阶段明确失败。
|
|
221
|
+
- [ ] 测试、预发布、生产使用不同密钥。
|
|
222
|
+
- [ ] Secret scanner 对当前提交和受支持的 Git 历史范围返回 0 个未豁免发现。
|
|
223
|
+
|
|
224
|
+
## S0-04 修正生产依赖和启动命令
|
|
225
|
+
|
|
226
|
+
### 当前问题
|
|
227
|
+
|
|
228
|
+
apps/server/package.json 中:
|
|
229
|
+
|
|
230
|
+
- @nestjs/swagger 被 main.ts 和 Controller 在运行时导入,却位于 devDependencies。
|
|
231
|
+
- shared/utils 被认证和 Session 代码在运行时导入,但 shared 位于 devDependencies。
|
|
232
|
+
- build:preview 执行 node dist/main。
|
|
233
|
+
- 当前实际构建入口位于 dist/src/main.js,build:preview 已实测出现 MODULE_NOT_FOUND。
|
|
234
|
+
|
|
235
|
+
仅安装生产依赖或在多阶段镜像中裁剪 devDependencies 后,Server 可能无法启动。
|
|
236
|
+
|
|
237
|
+
### TODO
|
|
238
|
+
|
|
239
|
+
- [ ] 把运行时需要的 shared 移到 dependencies。
|
|
240
|
+
- [ ] 把 @nestjs/swagger 移到 dependencies;当前 Controller 装饰器也会在模块加载时导入它,仅仅关闭 Swagger UI 不能消除运行时依赖。
|
|
241
|
+
- [ ] 检查 Swagger UI 在 Fastify 下对 @fastify/static 的运行时要求,并按实际启动路径调整依赖分类。
|
|
242
|
+
- [ ] 生产环境通过配置关闭文档生成和 /api-docs,但保留当前装饰器架构所需的运行依赖。
|
|
243
|
+
- [ ] 只有重构掉生产 bundle 中的全部 Swagger 装饰器/import 后,才可以考虑从生产依赖移除 @nestjs/swagger。
|
|
244
|
+
- [ ] 修正构建输出目录或把生产启动命令改为实际入口。
|
|
245
|
+
- [ ] 增加明确的 start:prod 脚本。
|
|
246
|
+
- [ ] 统一 build、preview、Docker CMD 和部署平台启动命令。
|
|
247
|
+
- [ ] 使用仅 production dependencies 的干净环境验证启动。
|
|
248
|
+
|
|
249
|
+
### 验收标准
|
|
250
|
+
|
|
251
|
+
- [ ] vp run --filter server build 成功。
|
|
252
|
+
- [ ] 生产启动脚本能真正启动 dist 产物。
|
|
253
|
+
- [ ] 删除 devDependencies 后仍能启动生产 Server。
|
|
254
|
+
- [ ] shared 已构建并随发布产物提供。
|
|
255
|
+
|
|
256
|
+
## S0-05 把数据库迁移纳入版本控制
|
|
257
|
+
|
|
258
|
+
### 当前问题
|
|
259
|
+
|
|
260
|
+
本地已经存在 apps/server/drizzle 下的 SQL 和 meta 文件,但 apps/server/.gitignore 忽略整个 drizzle 目录,当前没有任何迁移进入 Git。
|
|
261
|
+
|
|
262
|
+
这意味着:
|
|
263
|
+
|
|
264
|
+
- 新环境无法从空数据库重复构建相同 schema。
|
|
265
|
+
- CI 无法验证迁移。
|
|
266
|
+
- 多人开发时数据库状态只能依赖手工 db:push。
|
|
267
|
+
- 回滚、审计和发布顺序不可追踪。
|
|
268
|
+
|
|
269
|
+
### TODO
|
|
270
|
+
|
|
271
|
+
- [ ] 从 apps/server/.gitignore 删除对整个 drizzle 目录的忽略。
|
|
272
|
+
- [ ] 提交 SQL、journal 和 snapshot。
|
|
273
|
+
- [ ] 明确开发使用 db:generate + db:migrate 的流程。
|
|
274
|
+
- [ ] 禁止生产部署依赖 db:push。
|
|
275
|
+
- [ ] 增加从空数据库执行所有迁移的 CI 测试。
|
|
276
|
+
- [ ] 增加初始化管理员或基础权限数据的可重复 seed 方案。
|
|
277
|
+
- [ ] 迁移任务只能由一个发布 Job 执行,不要由每个应用副本无锁执行。
|
|
278
|
+
|
|
279
|
+
### 验收标准
|
|
280
|
+
|
|
281
|
+
- [ ] 克隆仓库后可以在空 PostgreSQL 上完整迁移。
|
|
282
|
+
- [ ] 应用启动不负责并发执行 schema 迁移。
|
|
283
|
+
- [ ] CI 会检测未提交迁移和 schema 漂移。
|
|
284
|
+
|
|
285
|
+
## S0-06 落地统一异常、requestId 和安全响应
|
|
286
|
+
|
|
287
|
+
### 当前问题
|
|
288
|
+
|
|
289
|
+
当前只有 ResponseInterceptor 包装成功响应,没有 APP_FILTER。
|
|
290
|
+
|
|
291
|
+
实际会出现多种失败格式:
|
|
292
|
+
|
|
293
|
+
- 普通 HttpException。
|
|
294
|
+
- 带对象 response 的认证异常。
|
|
295
|
+
- ZodValidationException。
|
|
296
|
+
- 未知 Error。
|
|
297
|
+
- Redis ServiceUnavailableException。
|
|
298
|
+
|
|
299
|
+
同时没有:
|
|
300
|
+
|
|
301
|
+
- 稳定错误码目录。
|
|
302
|
+
- requestId。
|
|
303
|
+
- 统一 validation details。
|
|
304
|
+
- cause 链。
|
|
305
|
+
- 5xx 日志脱敏。
|
|
306
|
+
- 401 Bearer challenge。
|
|
307
|
+
- 前端只对 Session 401 清理登录态的约束。
|
|
308
|
+
|
|
309
|
+
### TODO
|
|
310
|
+
|
|
311
|
+
- [ ] 完整实施 04.exception.md。
|
|
312
|
+
- [ ] 业务失败使用真实 4xx/5xx,禁止 HTTP 200 表示失败。
|
|
313
|
+
- [ ] 错误码使用稳定、带命名空间的字符串。
|
|
314
|
+
- [ ] 未知 500 永不向客户端返回内部 message、stack、SQL 或连接信息。
|
|
315
|
+
- [ ] 401 与 Bearer challenge 保持 RFC 语义。
|
|
316
|
+
- [ ] 当前项目契约把普通 JSON 登录凭据错误定义为 422,并通过稳定错误码避免误触发 Session 过期处理。
|
|
317
|
+
- [ ] 如果未来改成 OAuth 2.0 Token Endpoint,重新按对应规范评估 400 invalid_grant,不把 422 当成所有认证系统的唯一答案。
|
|
318
|
+
- [ ] 429/503 的 Retry-After 由真正知道重试窗口的组件设置。
|
|
319
|
+
- [ ] 未处理的 HTTP 5xx 技术异常只在 HTTP 边界记录一次;启动、后台任务、RPC/WS 和安全审计使用各自独立边界。
|
|
320
|
+
|
|
321
|
+
### 验收标准
|
|
322
|
+
|
|
323
|
+
- [ ] 400、401、403、404、409、422、429、503、500 都符合统一契约。
|
|
324
|
+
- [ ] 响应头、错误体和日志中的 requestId 一致。
|
|
325
|
+
- [ ] 500 响应不泄露内部信息。
|
|
326
|
+
- [ ] Session 401 含 WWW-Authenticate。
|
|
327
|
+
- [ ] 登录 422 不含 Bearer challenge。
|
|
328
|
+
|
|
329
|
+
## S0-07 阻止公开注册和登录接口被滥用
|
|
330
|
+
|
|
331
|
+
### 当前问题
|
|
332
|
+
|
|
333
|
+
- 注册接口完全公开。
|
|
334
|
+
- 登录和注册没有限流。
|
|
335
|
+
- 用户不存在或状态不可用时直接返回,不执行 Argon2 verify。
|
|
336
|
+
- 错误密码路径会执行 Argon2,因此可以通过耗时差异推测账号是否存在。
|
|
337
|
+
- Argon2 是高成本操作,没有限流时也可能成为计算型 DoS 入口。
|
|
338
|
+
|
|
339
|
+
### TODO
|
|
340
|
+
|
|
341
|
+
- [ ] 明确管理后台是否允许任何人公开注册。
|
|
342
|
+
- [ ] 如果不允许,改成管理员创建、邀请注册或初始化一次性超级管理员。
|
|
343
|
+
- [ ] 登录按账号和 IP 两个维度限流。
|
|
344
|
+
- [ ] 注册按 IP、设备和业务标识限流。
|
|
345
|
+
- [ ] 账号不存在时验证固定 dummy Argon2 hash。
|
|
346
|
+
- [ ] 登录失败使用统一响应,不暴露账号存在、锁定或禁用的具体原因。
|
|
347
|
+
- [ ] 增加渐进延迟或短期锁定,但避免永久锁死成为 DoS 手段。
|
|
348
|
+
- [ ] 429 返回安全文案和 Retry-After。
|
|
349
|
+
- [ ] 记录登录成功、失败、锁定和限流安全事件。
|
|
350
|
+
|
|
351
|
+
### 验收标准
|
|
352
|
+
|
|
353
|
+
- [ ] 单元测试证明“不存在账号”分支也调用固定 dummy Argon2 verify,并与错误密码返回完全相同的 HTTP 状态、错误码和公开文案。
|
|
354
|
+
- [ ] 在固定测试机预热后各采样至少 100 次,不存在账号与错误密码的中位耗时不得出现数量级差异;阈值由项目基准测试记录,而不是写死为跨机器通用值。
|
|
355
|
+
- [ ] 并发爆破请求会被限流。
|
|
356
|
+
- [ ] 普通访客不能自行获得管理后台账号,除非产品明确允许。
|
|
357
|
+
|
|
358
|
+
---
|
|
359
|
+
|
|
360
|
+
# P1:生产级后端基线
|
|
361
|
+
|
|
362
|
+
## S1-01 建立统一、强类型、启动即校验的配置系统
|
|
363
|
+
|
|
364
|
+
### 当前缺口
|
|
365
|
+
|
|
366
|
+
- ConfigModule.forRoot 没有统一 validate/schema。
|
|
367
|
+
- PORT、DB_PORT、REDIS_PORT 可能被解析为 NaN。
|
|
368
|
+
- 数据库、Redis 必填项不能在启动阶段完整校验。
|
|
369
|
+
- main.ts 直接读取 process.env,没有使用 appConfig。
|
|
370
|
+
- Drizzle CLI 使用 DATABASE_URL,运行时 Pool 使用 DB_HOST、DB_PORT 等另一套配置。
|
|
371
|
+
- llm.config.ts 被加载,但当前没有任何消费者。
|
|
372
|
+
|
|
373
|
+
### TODO
|
|
374
|
+
|
|
375
|
+
- [ ] 使用 Zod 建立完整 EnvSchema。
|
|
376
|
+
- [ ] 在 ConfigModule 启动时一次性 fail fast。
|
|
377
|
+
- [ ] DATABASE_URL 与分散 DB 字段只保留一个事实源。
|
|
378
|
+
- [ ] main.ts 通过 ConfigService 读取 host、port、environment。
|
|
379
|
+
- [ ] 校验端口范围、URL、TTL 关系、密钥长度和枚举值。
|
|
380
|
+
- [ ] 删除没有消费者的 JWT、LLM 等遗留配置,或实现对应模块后再加入。
|
|
381
|
+
- [ ] 为 development、test、production 明确必需项和默认值策略。
|
|
382
|
+
|
|
383
|
+
## S1-02 完成 PostgreSQL 数据层生命周期
|
|
384
|
+
|
|
385
|
+
### 当前缺口
|
|
386
|
+
|
|
387
|
+
- Pool 只在工厂函数中创建,没有单独 provider,也没有关闭钩子。
|
|
388
|
+
- 没有 SSL、connection timeout、statement timeout、pool max、idle timeout。
|
|
389
|
+
- 没有 application_name。
|
|
390
|
+
- 没有通用 PostgreSQL SQLSTATE 映射。
|
|
391
|
+
- createdAt 和 updatedAt 的时区类型不一致。
|
|
392
|
+
- updatedAt 不会自动更新。
|
|
393
|
+
|
|
394
|
+
### TODO
|
|
395
|
+
|
|
396
|
+
- [ ] 将 Pool 作为独立 provider 暴露。
|
|
397
|
+
- [ ] 在 OnApplicationShutdown 或 OnModuleDestroy 中调用 pool.end。
|
|
398
|
+
- [ ] 根据环境配置 SSL、连接池大小和超时。
|
|
399
|
+
- [ ] 统一使用 UTC/timestamptz。
|
|
400
|
+
- [ ] 为 updatedAt 建立可靠的自动更新策略。
|
|
401
|
+
- [ ] 根据已确认的查询计划、排序和关联场景增加索引,并用 EXPLAIN/集成基准验证;不要无条件给所有字段加索引。
|
|
402
|
+
- [ ] 只有出现跨 Repository 事务时再建立 transaction helper 或 Unit of Work 约定。
|
|
403
|
+
- [ ] 按 SQLSTATE 集中映射错误:
|
|
404
|
+
- 23505 唯一约束:409。
|
|
405
|
+
- 23503 外键约束:根据“资源冲突”或“输入语义无效”映射为 409/422,不做全局硬编码。
|
|
406
|
+
- 40001 序列化失败:只在完整、可幂等重放的事务边界有限重试。
|
|
407
|
+
- 40P01 死锁:只在完整、可幂等重放的事务边界有限重试。
|
|
408
|
+
- [ ] 40001/40P01 重试耗尽后的 409、503 或其他状态由具体操作语义决定。
|
|
409
|
+
- [ ] 不解析数据库 message 判断错误类型。
|
|
410
|
+
|
|
411
|
+
## S1-03 增加健康检查、启动边界和优雅停机
|
|
412
|
+
|
|
413
|
+
### 当前缺口
|
|
414
|
+
|
|
415
|
+
- 根路径仍返回 Hello World。
|
|
416
|
+
- 没有 /health/live。
|
|
417
|
+
- 没有 /health/ready。
|
|
418
|
+
- /db 和 /redis/ping 是受保护调试路由,不是健康检查。
|
|
419
|
+
- bootstrap 末尾只有 void bootstrap(),没有明确的启动失败处理。
|
|
420
|
+
- 没有 enableShutdownHooks。
|
|
421
|
+
- 数据库 Pool 没有关闭。
|
|
422
|
+
|
|
423
|
+
### TODO
|
|
424
|
+
|
|
425
|
+
- [ ] 提供轻量 liveness,只表示进程事件循环仍工作。
|
|
426
|
+
- [ ] 提供 readiness,检查 PostgreSQL 和 Redis,并设置严格超时。
|
|
427
|
+
- [ ] readiness 失败时返回非健康状态,由负载均衡器或编排器摘除实例。
|
|
428
|
+
- [ ] 启用 Nest shutdown hooks。
|
|
429
|
+
- [ ] SIGTERM 进入独立 draining 流程:先让 readiness 失败并等待流量摘除,再关闭 HTTP、Redis、PostgreSQL。
|
|
430
|
+
- [ ] bootstrap 失败记录结构化 fatal 日志并设置非零退出码。
|
|
431
|
+
- [ ] Docker Compose 和生产编排使用 healthcheck,而不是固定 sleep。
|
|
432
|
+
|
|
433
|
+
## S1-04 建立 requestId、结构化日志和安全审计
|
|
434
|
+
|
|
435
|
+
边界说明:S0-06 只完成 requestId 的生成、错误响应和 HTTP 异常关联;本节把它扩展到访问日志、应用上下文、统一脱敏和安全事件。可查询的长期审计管理模块放在 S2-04。
|
|
436
|
+
|
|
437
|
+
### 当前缺口
|
|
438
|
+
|
|
439
|
+
- Fastify request logger 未开启。
|
|
440
|
+
- 没有可信 requestId。
|
|
441
|
+
- 没有请求耗时、route template、status、error code 访问日志。
|
|
442
|
+
- 没有统一嵌套脱敏。
|
|
443
|
+
- 没有登录与权限安全审计。
|
|
444
|
+
|
|
445
|
+
### TODO
|
|
446
|
+
|
|
447
|
+
- [ ] 由 Server 生成 UUID/ULID requestId。
|
|
448
|
+
- [ ] 如接收入站 requestId,只接受受限格式和长度,否则重新生成。
|
|
449
|
+
- [ ] 响应头、错误体、日志使用同一个 requestId。
|
|
450
|
+
- [ ] 使用 Pino 或等价结构化日志。
|
|
451
|
+
- [ ] 日志记录 route template,不记录原始 URL/query。
|
|
452
|
+
- [ ] 默认不记录 request/response body。
|
|
453
|
+
- [ ] 深层脱敏 Authorization、Cookie、Token、密码、密钥、连接串和 PII。
|
|
454
|
+
- [ ] 5xx 保留有限 cause 链,4xx 不默认打印 stack。
|
|
455
|
+
- [ ] 增加登录成功、失败、登出、踢人、改密、权限拒绝审计事件。
|
|
456
|
+
- [ ] 定义日志保留周期、查询权限和删除策略。
|
|
457
|
+
|
|
458
|
+
## S1-05 完成 HTTP 安全基线
|
|
459
|
+
|
|
460
|
+
### 当前缺口
|
|
461
|
+
|
|
462
|
+
- CORS origin 为通配。
|
|
463
|
+
- Swagger 在所有环境公开。
|
|
464
|
+
- trustProxy 固定为本地回环地址。
|
|
465
|
+
- 没有 Helmet。
|
|
466
|
+
- 没有全局与接口级限流。
|
|
467
|
+
- 没有明确 body 大小、请求超时和响应压缩策略。
|
|
468
|
+
|
|
469
|
+
### TODO
|
|
470
|
+
|
|
471
|
+
- [ ] 生产 CORS 使用配置化 allowlist。
|
|
472
|
+
- [ ] 只暴露实际需要的 headers 和 methods。
|
|
473
|
+
- [ ] Swagger 在生产关闭,或使用独立鉴权。
|
|
474
|
+
- [ ] 启用 Fastify Helmet,并根据前端部署调整 CSP。
|
|
475
|
+
- [ ] 配置全局基础限流和登录专项限流。
|
|
476
|
+
- [ ] trustProxy 根据真实代理拓扑配置,不能盲目信任所有来源。
|
|
477
|
+
- [ ] 限制 JSON、表单和上传 body 大小。
|
|
478
|
+
- [ ] 为慢请求设置应用和下游超时,但不能把 RxJS timeout 当成取消数据库操作。
|
|
479
|
+
- [ ] Bearer Header 模式不需要 CSRF Token;如果以后改用 Cookie,再增加 SameSite、Secure 和 CSRF 防护。
|
|
480
|
+
|
|
481
|
+
## S1-06 补齐账号和 Session 生命周期
|
|
482
|
+
|
|
483
|
+
### 当前缺口
|
|
484
|
+
|
|
485
|
+
- revokeAllForUser 已存在,但没有任何调用方或 API。
|
|
486
|
+
- 禁用、锁定用户后,已有 Session 不会自动撤销。
|
|
487
|
+
- Guard 只验证 Redis 中的 userId 和 terminal。
|
|
488
|
+
- 没有改密后的强制撤销和用户主动退出全部终端。
|
|
489
|
+
- 没有 Argon2 参数版本和 needsRehash。
|
|
490
|
+
|
|
491
|
+
### TODO
|
|
492
|
+
|
|
493
|
+
- [ ] 增加修改密码接口。
|
|
494
|
+
- [ ] 改密、禁用、锁定、删除用户后撤销全部 Session。
|
|
495
|
+
- [ ] 增加当前用户退出全部终端。
|
|
496
|
+
- [ ] 明确普通接口多久重新确认用户状态。
|
|
497
|
+
- [ ] 为关键接口提供强制回源确认策略。
|
|
498
|
+
- [ ] 显式配置并基准测试 Argon2id 参数。
|
|
499
|
+
- [ ] 参数升级后在登录成功时执行 needsRehash。
|
|
500
|
+
- [ ] 原始 Token、Token digest、密码和 passwordHash 永不进入日志。
|
|
501
|
+
|
|
502
|
+
管理员重置密码、在线终端列表和踢指定设备属于管理产品能力,放在 S2-01 与 S2-10。
|
|
503
|
+
|
|
504
|
+
注意:当前 Opaque Redis Session 适合强撤销需求,不需要因为参考项目使用 JWT 就改成 JWT + Refresh Token。应先把现有 Session 做正确。
|
|
505
|
+
|
|
506
|
+
## S1-07 建立最小授权内核
|
|
507
|
+
|
|
508
|
+
### 当前缺口
|
|
509
|
+
|
|
510
|
+
当前只有“是否登录”,没有:
|
|
511
|
+
|
|
512
|
+
- 管理员与普通用户边界。
|
|
513
|
+
- 默认拒绝的敏感路由策略。
|
|
514
|
+
- 最小权限码和权限 Guard。
|
|
515
|
+
- Resource ownership 检查约定。
|
|
516
|
+
|
|
517
|
+
### TODO
|
|
518
|
+
|
|
519
|
+
- [ ] 先定义最小、稳定权限码,例如 system.user.read。
|
|
520
|
+
- [ ] 增加 Permissions 装饰器和 Guard/Policy。
|
|
521
|
+
- [ ] 管理模块采用默认拒绝;未声明权限不能自动放行。
|
|
522
|
+
- [ ] 超级管理员能力必须显式、可审计。
|
|
523
|
+
- [ ] 第一阶段可以使用受控静态策略或最小角色字段,但不能继续让所有登录用户权限相同。
|
|
524
|
+
- [ ] 涉及单条资源时同时检查权限和数据归属。
|
|
525
|
+
- [ ] 为每个敏感 Controller 建立权限契约测试。
|
|
526
|
+
|
|
527
|
+
完整动态角色表、权限关联、缓存失效以及公司/租户模型放在 S2-02 与 S2-03。当前 CORS 已允许 X-Company-Id,但 Server 没有任何公司校验;在 S2-03 完成前不要让业务依赖该 Header。
|
|
528
|
+
|
|
529
|
+
## S1-08 让响应 schema 和 OpenAPI 真正成为契约
|
|
530
|
+
|
|
531
|
+
### 当前缺口
|
|
532
|
+
|
|
533
|
+
虽然全局注册了 ZodSerializerInterceptor,但全仓没有使用运行时响应 DTO 元数据,因此“响应防泄漏”实际上没有形成覆盖。
|
|
534
|
+
|
|
535
|
+
### TODO
|
|
536
|
+
|
|
537
|
+
- [ ] 至少为 auth/me、注册、登录等敏感接口声明运行时响应 schema。
|
|
538
|
+
- [ ] 为统一成功响应和失败响应定义基础 schema。
|
|
539
|
+
- [ ] 不依赖 TypeScript 返回类型做运行时脱敏。
|
|
540
|
+
- [ ] shared ApiResponse 增加稳定字符串 code、requestId 和受限 details。
|
|
541
|
+
- [ ] Auth 与基础错误端点的 OpenAPI 声明覆盖实际状态码。
|
|
542
|
+
- [ ] 故意向 Service 结果插入 passwordHash,测试应证明响应不会泄漏。
|
|
543
|
+
|
|
544
|
+
全接口 schema、前端类型生成和 OpenAPI snapshot 属于 S2-11 的完整契约建设。
|
|
545
|
+
|
|
546
|
+
## S1-09 建立真正的 Server 自动化测试
|
|
547
|
+
|
|
548
|
+
### 当前缺口
|
|
549
|
+
|
|
550
|
+
- apps/server 没有 spec/test 文件。
|
|
551
|
+
- package.json 没有 test script。
|
|
552
|
+
- @nestjs/testing 已安装但没有使用。
|
|
553
|
+
- Nest SWC 构建关闭 typeCheck。
|
|
554
|
+
- package.json 的 format 仍调用当前工作区没有配置的 Prettier。
|
|
555
|
+
|
|
556
|
+
### TODO
|
|
557
|
+
|
|
558
|
+
- [ ] 增加 Server 的 Vite/Vitest 配置和 test script。
|
|
559
|
+
- [ ] 使用 vp test,而不是 Jest 命令。
|
|
560
|
+
- [ ] 单元测试覆盖错误目录、Guard、Service、Repository mapper。
|
|
561
|
+
- [ ] 使用 Fastify inject 编写 HTTP 集成测试。
|
|
562
|
+
- [ ] 使用真实 PostgreSQL/Redis 测试关键基础设施。
|
|
563
|
+
- [ ] Redis Lua 测试覆盖并发和竞态。
|
|
564
|
+
- [ ] 测试 passwordHash、Token、stack 和连接串不会泄漏。
|
|
565
|
+
- [ ] 测试 requestId 并发不串线。
|
|
566
|
+
- [ ] 测试 RBAC 默认拒绝。
|
|
567
|
+
- [ ] 为关键路径设置覆盖率门槛。
|
|
568
|
+
- [ ] 修正 Server format script,统一使用 Vite+ Oxfmt。
|
|
569
|
+
|
|
570
|
+
## S1-10 建立发布与 CI/CD 闭环
|
|
571
|
+
|
|
572
|
+
### TODO
|
|
573
|
+
|
|
574
|
+
- [ ] 增加多阶段 Server Dockerfile。
|
|
575
|
+
- [ ] 使用非 root 用户运行。
|
|
576
|
+
- [ ] 镜像只包含运行依赖和必要构建产物。
|
|
577
|
+
- [ ] 不把 .env 或 Secret 复制进镜像。
|
|
578
|
+
- [ ] 发布前独立执行数据库迁移。
|
|
579
|
+
- [ ] CI 执行 vp install、shared build、vp check、workspace test、workspace build。
|
|
580
|
+
- [ ] CI 从空数据库验证迁移。
|
|
581
|
+
- [ ] CI 使用生产依赖镜像实际启动 Server 并检查 readiness。
|
|
582
|
+
- [ ] 增加会自动启动、限时轮询 readiness、终止子进程并返回退出码的 bounded smoke script。
|
|
583
|
+
- [ ] 建立回滚、数据库备份和恢复演练。
|
|
584
|
+
- [ ] docker-compose.yml 明确标记为开发环境。
|
|
585
|
+
- [ ] 开发 Compose 不使用 latest 镜像标签,并加入 healthcheck。
|
|
586
|
+
- [ ] 生产不直接公开 PostgreSQL、Redis 和 MinIO 管理端口。
|
|
587
|
+
|
|
588
|
+
## S1-11 建立首个生产环境所需的最小指标与告警
|
|
589
|
+
|
|
590
|
+
完整分布式追踪可以后置,但首个生产环境不能只有日志。
|
|
591
|
+
|
|
592
|
+
### TODO
|
|
593
|
+
|
|
594
|
+
- [ ] 采集 HTTP request count、duration 和 error rate,route 使用模板而不是原始 URL。
|
|
595
|
+
- [ ] 按 HTTP status 和稳定 error code 聚合失败。
|
|
596
|
+
- [ ] 监控 PostgreSQL pool 使用量、等待数和连接失败。
|
|
597
|
+
- [ ] 监控 Redis 连接状态、命令延迟和错误。
|
|
598
|
+
- [ ] 聚合未知 5xx,并建立错误率与 readiness 告警。
|
|
599
|
+
- [ ] 登录失败、限流和权限拒绝建立安全告警,但控制标签基数。
|
|
600
|
+
- [ ] 为每个告警编写负责人、影响判断和处理步骤。
|
|
601
|
+
|
|
602
|
+
## P1 自动化验收矩阵
|
|
603
|
+
|
|
604
|
+
| 能力 | 可执行验收 |
|
|
605
|
+
| --------------- | ---------------------------------------------------------------------------------------------------- |
|
|
606
|
+
| 配置 | 表驱动测试逐个删除或破坏必需变量,应用必须在监听端口前失败并指出变量名 |
|
|
607
|
+
| 数据库生命周期 | 集成测试启动应用后发送 SIGTERM,Pool 在超时内结束且进程以预期状态退出 |
|
|
608
|
+
| 健康检查 | 正常时 ready=200;断开 Redis 或 PostgreSQL 时 ready 非 2xx、live 仍为 200;恢复后 ready 回到 200 |
|
|
609
|
+
| requestId | 并发请求的响应头、错误体、访问日志一一对应,没有串号 |
|
|
610
|
+
| 日志脱敏 | 属性测试覆盖对象、数组、大小写变体和 CR/LF,输出中不存在测试 Token、密码、Cookie、连接串 |
|
|
611
|
+
| CORS 与 Swagger | Fastify e2e 覆盖允许/拒绝 Origin;production 配置下 /api-docs 不可匿名访问 |
|
|
612
|
+
| Session 强撤销 | 禁用、锁定或改密事务完成后,旧 Token 的下一次请求返回 Session 401 |
|
|
613
|
+
| 最小授权 | 路由矩阵测试证明匿名=401、已登录无权限=403、有权限=成功,未声明权限的管理路由默认拒绝 |
|
|
614
|
+
| 响应防泄漏 | Service 故意返回 passwordHash,外部响应中仍不存在该字段 |
|
|
615
|
+
| 测试接入 | vp run --filter server test 能实际发现并执行 Server 测试,失败测试使进程非零退出 |
|
|
616
|
+
| 生产镜像 | 仅安装 production dependencies 的镜像启动成功,迁移完成后 bounded smoke test 能探测 ready 并终止进程 |
|
|
617
|
+
| 指标与告警 | 测试请求能产生预期 RED 指标;模拟未知 5xx 与依赖故障能触发测试告警规则 |
|
|
618
|
+
|
|
619
|
+
---
|
|
620
|
+
|
|
621
|
+
# P2:完整管理后台能力
|
|
622
|
+
|
|
623
|
+
以下能力是 nest-admin 一类成熟管理后台通常具备,而当前项目尚未实现的部分。是否全部实施取决于产品范围。
|
|
624
|
+
|
|
625
|
+
## S2-01 用户管理
|
|
626
|
+
|
|
627
|
+
- [ ] 分页查询用户。
|
|
628
|
+
- [ ] 创建、编辑、禁用、锁定和软删除用户。
|
|
629
|
+
- [ ] 管理员重置密码。
|
|
630
|
+
- [ ] 修改用户状态时撤销 Session。
|
|
631
|
+
- [ ] 查询用户角色、公司、部门和在线状态。
|
|
632
|
+
- [ ] 所有列表明确 select 字段,永不返回 passwordHash。
|
|
633
|
+
- [ ] 增加乐观锁或版本字段,避免后台多人覆盖修改。
|
|
634
|
+
|
|
635
|
+
## S2-02 角色、权限和动态菜单
|
|
636
|
+
|
|
637
|
+
- [ ] 建立 role、permission、user_role、role_permission 等迁移。
|
|
638
|
+
- [ ] 角色 CRUD。
|
|
639
|
+
- [ ] 权限码目录。
|
|
640
|
+
- [ ] 角色与权限关联。
|
|
641
|
+
- [ ] 用户与角色关联。
|
|
642
|
+
- [ ] 菜单与路由元数据。
|
|
643
|
+
- [ ] 菜单只负责展示,后端权限 Guard 才是安全边界。
|
|
644
|
+
- [ ] 权限变更审计。
|
|
645
|
+
- [ ] 权限缓存使用版本号或明确失效事件;测试证明变更后不会长期沿用旧权限。
|
|
646
|
+
- [ ] 明确权限变更是否立即撤销 Session,或让下一次强校验刷新授权状态。
|
|
647
|
+
- [ ] 初始化超级管理员和最小角色。
|
|
648
|
+
|
|
649
|
+
## S2-03 公司、部门、岗位或租户
|
|
650
|
+
|
|
651
|
+
- [ ] 先确认产品是否真的需要多公司或多租户。
|
|
652
|
+
- [ ] 需要时建立 company/tenant、membership、department 等表。
|
|
653
|
+
- [ ] 当前公司必须由服务端验证。
|
|
654
|
+
- [ ] Repository 查询默认带租户条件。
|
|
655
|
+
- [ ] 唯一索引包含租户边界。
|
|
656
|
+
- [ ] 增加跨租户越权测试。
|
|
657
|
+
- [ ] 不要因为 Soybean 有 tenant 模块就盲目引入。
|
|
658
|
+
|
|
659
|
+
## S2-04 操作日志、登录日志和安全审计
|
|
660
|
+
|
|
661
|
+
P1 先保证安全事件会被结构化记录和告警;本节建设可持久化、可查询、受权限控制的管理模块。
|
|
662
|
+
|
|
663
|
+
- [ ] 登录成功与失败日志。
|
|
664
|
+
- [ ] 注册、登出、踢人、改密日志。
|
|
665
|
+
- [ ] 管理员增删改操作日志。
|
|
666
|
+
- [ ] 记录操作对象、结果、requestId 和受控用户标识。
|
|
667
|
+
- [ ] 不保存原始请求 body、密码、Token 或敏感字段。
|
|
668
|
+
- [ ] 支持分页查询、权限控制和保留周期。
|
|
669
|
+
|
|
670
|
+
## S2-05 字典、系统配置和 Feature Flag
|
|
671
|
+
|
|
672
|
+
- [ ] 公共字典与状态码配置。
|
|
673
|
+
- [ ] 系统参数配置。
|
|
674
|
+
- [ ] 配置变更审计。
|
|
675
|
+
- [ ] 敏感配置不进入普通配置表。
|
|
676
|
+
- [ ] Feature Flag 有默认值、作用域和回滚能力。
|
|
677
|
+
|
|
678
|
+
## S2-06 文件上传与 MinIO
|
|
679
|
+
|
|
680
|
+
当前 docker-compose.yml 已启动 MinIO,但 Server 完全没有对象存储模块。
|
|
681
|
+
|
|
682
|
+
- [ ] 定义 StoragePort,避免业务直接依赖 MinIO SDK。
|
|
683
|
+
- [ ] 限制文件大小、类型和扩展名。
|
|
684
|
+
- [ ] 服务端重新生成对象 Key,不能信任客户端文件名。
|
|
685
|
+
- [ ] 私有文件使用短期签名 URL。
|
|
686
|
+
- [ ] 增加病毒扫描或异步安全检查。
|
|
687
|
+
- [ ] 记录文件所有者、租户、用途和生命周期。
|
|
688
|
+
- [ ] 删除业务记录时处理对象清理和失败补偿。
|
|
689
|
+
|
|
690
|
+
## S2-07 定时任务、队列和 Worker
|
|
691
|
+
|
|
692
|
+
- [ ] 明确哪些任务需要异步化。
|
|
693
|
+
- [ ] 选择 BullMQ 或其他队列后建立统一 Job 契约。
|
|
694
|
+
- [ ] Job 必须幂等。
|
|
695
|
+
- [ ] 设置有限重试、指数退避、超时和 DLQ。
|
|
696
|
+
- [ ] 记录 jobId、requestId、错误码和最终状态。
|
|
697
|
+
- [ ] 多副本定时任务必须加分布式锁或独立 Scheduler。
|
|
698
|
+
- [ ] 提供失败任务查看和人工重试能力。
|
|
699
|
+
|
|
700
|
+
## S2-08 通知、邮件和站内消息
|
|
701
|
+
|
|
702
|
+
- [ ] 通知模板。
|
|
703
|
+
- [ ] 站内消息。
|
|
704
|
+
- [ ] 邮件或短信适配器。
|
|
705
|
+
- [ ] 发送任务进入队列。
|
|
706
|
+
- [ ] 失败重试和供应商切换。
|
|
707
|
+
- [ ] 退订、频控和审计。
|
|
708
|
+
|
|
709
|
+
## S2-09 导入、导出和批量操作
|
|
710
|
+
|
|
711
|
+
- [ ] 大文件异步处理。
|
|
712
|
+
- [ ] 导入逐行错误报告。
|
|
713
|
+
- [ ] 导出权限与字段脱敏。
|
|
714
|
+
- [ ] 批量操作幂等。
|
|
715
|
+
- [ ] 限制数据量,避免阻塞 HTTP 进程。
|
|
716
|
+
|
|
717
|
+
## S2-10 在线会话与后台控制台
|
|
718
|
+
|
|
719
|
+
- [ ] 查询用户当前终端列表。
|
|
720
|
+
- [ ] 管理员踢指定终端。
|
|
721
|
+
- [ ] 管理员撤销用户全部会话。
|
|
722
|
+
- [ ] 展示登录时间、最近活动时间、脱敏 IP 和 User-Agent。
|
|
723
|
+
- [ ] 在线状态只是近似值,不能当权限依据。
|
|
724
|
+
|
|
725
|
+
## S2-11 完整 API 契约与客户端类型
|
|
726
|
+
|
|
727
|
+
- [ ] 所有公开接口声明运行时成功响应 schema。
|
|
728
|
+
- [ ] OpenAPI 声明 400、401、403、404、409、422、429、500、503。
|
|
729
|
+
- [ ] 生成 React/Vue 共用的客户端协议类型。
|
|
730
|
+
- [ ] 增加 OpenAPI snapshot/contract test。
|
|
731
|
+
- [ ] 定义字段和错误码的兼容、弃用与迁移规则。
|
|
732
|
+
- [ ] 文档与运行时响应不一致时让 CI 失败。
|
|
733
|
+
|
|
734
|
+
## S2-12 Dashboard、统计与报表
|
|
735
|
+
|
|
736
|
+
- [ ] 只提供有明确业务含义的聚合指标。
|
|
737
|
+
- [ ] 统计查询具备时间范围、分页或上限。
|
|
738
|
+
- [ ] 大查询进入异步任务或报表库,不阻塞主业务数据库。
|
|
739
|
+
- [ ] 统计结果遵守角色、租户和数据范围权限。
|
|
740
|
+
- [ ] 为昂贵聚合建立缓存失效与容量策略。
|
|
741
|
+
|
|
742
|
+
## P2 统一验收标准
|
|
743
|
+
|
|
744
|
+
- [ ] 每个新增模块都有迁移、DTO、Service/Repository、权限码和响应 schema。
|
|
745
|
+
- [ ] 路由矩阵覆盖匿名、无权限、有权限、跨数据范围四类请求。
|
|
746
|
+
- [ ] 列表接口有默认上限和最大上限,空条件请求不能无限返回全表。
|
|
747
|
+
- [ ] 敏感变更产生可查询审计事件。
|
|
748
|
+
- [ ] 文件、队列、通知等外部依赖失败时有稳定错误码和补偿/重试规则。
|
|
749
|
+
- [ ] OpenAPI 契约和 e2e 测试随模块一起提交。
|
|
750
|
+
- [ ] 对应模块未被产品选择时保持未实现,不为了勾选清单引入空壳依赖。
|
|
751
|
+
|
|
752
|
+
---
|
|
753
|
+
|
|
754
|
+
# P3:按规模和产品需要实施
|
|
755
|
+
|
|
756
|
+
## S3-01 OpenTelemetry、跨服务追踪和高级错误聚合
|
|
757
|
+
|
|
758
|
+
- [ ] OTel instrumentation 在 Nest、Fastify、HTTP 和数据库模块导入前启动。
|
|
759
|
+
- [ ] 日志自动关联 traceId 和 spanId。
|
|
760
|
+
- [ ] 定义采样策略、跨服务传播和敏感属性过滤。
|
|
761
|
+
- [ ] Trace、日志和 P1 基础指标使用同一服务与环境标识。
|
|
762
|
+
- [ ] 只把未知 5xx 上报 Sentry,避免 Filter、OTel、Sentry 重复记录。
|
|
763
|
+
- [ ] 在引入消息队列或其他服务后验证异步上下文传播。
|
|
764
|
+
|
|
765
|
+
## S3-02 MFA、SSO 与企业身份
|
|
766
|
+
|
|
767
|
+
- [ ] 产品明确需要后再实现 TOTP、Passkey、OIDC 或 SAML。
|
|
768
|
+
- [ ] MFA 恢复码必须加密或哈希保存。
|
|
769
|
+
- [ ] SSO 账号绑定和离职撤销必须可审计。
|
|
770
|
+
- [ ] 不把验证码当成唯一的登录防护。
|
|
771
|
+
|
|
772
|
+
## S3-03 Session 扩展与 Redis 高可用
|
|
773
|
+
|
|
774
|
+
当前每次受保护请求都会写 Redis 续期,高流量时存在写放大。
|
|
775
|
+
|
|
776
|
+
- [ ] 评估按时间窗口节流续期写入。
|
|
777
|
+
- [ ] 明确 Redis 持久化、maxmemory、noeviction 和容量告警。
|
|
778
|
+
- [ ] 如迁移 Redis Cluster,为多 Key Lua 设计 hash tag。
|
|
779
|
+
- [ ] 评估 Sentinel、Cluster 或托管 Redis。
|
|
780
|
+
- [ ] 定义 Redis 故障时认证是 fail closed 还是有限降级。
|
|
781
|
+
|
|
782
|
+
## S3-04 多传输层错误 Presenter
|
|
783
|
+
|
|
784
|
+
- [ ] 只有引入 GraphQL 时才实现 GraphQL extensions 错误格式。
|
|
785
|
+
- [ ] 只有引入 WebSocket 时才实现 WsExceptionFilter。
|
|
786
|
+
- [ ] 只有引入微服务 Transport 时才实现 RpcExceptionFilter。
|
|
787
|
+
- [ ] 不让 HTTP Filter 盲目处理所有 ArgumentsHost 类型。
|
|
788
|
+
|
|
789
|
+
## S3-05 幂等、Outbox 与分布式一致性
|
|
790
|
+
|
|
791
|
+
- [ ] 对支付、创建订单、批量提交等关键写接口使用调用方 Idempotency-Key。
|
|
792
|
+
- [ ] 幂等状态必须包含用户或租户作用域。
|
|
793
|
+
- [ ] 使用 Redis 原子状态机或数据库唯一约束。
|
|
794
|
+
- [ ] 出现跨系统事件后再引入 Outbox。
|
|
795
|
+
- [ ] Worker 支持 claim、lease、重试和死信。
|
|
796
|
+
|
|
797
|
+
## S3-06 API 版本化与兼容策略
|
|
798
|
+
|
|
799
|
+
- [ ] 在 API 对外稳定或存在多版本客户端前决定 URI、Header 或媒体类型版本策略。
|
|
800
|
+
- [ ] 定义错误码和响应字段的兼容规则。
|
|
801
|
+
- [ ] 定义弃用通知、支持窗口和删除条件。
|
|
802
|
+
- [ ] 契约测试覆盖仍在支持期内的旧客户端。
|
|
803
|
+
- [ ] 不仅修改 Swagger 的版本文字,运行时路由和兼容行为必须一致。
|
|
804
|
+
|
|
805
|
+
## P3 实施门槛
|
|
806
|
+
|
|
807
|
+
- [ ] 有明确产品需求、SLO、合规要求或容量数据支持实施。
|
|
808
|
+
- [ ] 先写 ADR,说明不实施、简单方案和复杂方案的取舍。
|
|
809
|
+
- [ ] 有负载、故障或兼容测试证明新复杂度解决了真实问题。
|
|
810
|
+
- [ ] 有成本、回滚、运维负责人和告警策略。
|
|
811
|
+
|
|
812
|
+
---
|
|
813
|
+
|
|
814
|
+
# 3. 不建议从参考项目照搬的做法
|
|
815
|
+
|
|
816
|
+
## 3.1 不要返回 HTTP 200 表示业务失败
|
|
817
|
+
|
|
818
|
+
业务码与 HTTP 状态是两层协议:
|
|
819
|
+
|
|
820
|
+
- HTTP 表示传输和通用语义。
|
|
821
|
+
- 稳定错误码表示具体业务原因。
|
|
822
|
+
|
|
823
|
+
不要让网关、缓存、监控和浏览器把失败统计成成功。
|
|
824
|
+
|
|
825
|
+
## 3.2 不要用 code:message 字符串再 split
|
|
826
|
+
|
|
827
|
+
错误码、公开文案、HTTP 状态、是否可重试应是结构化字段。
|
|
828
|
+
|
|
829
|
+
也不要把 HTTP 数字 200/400/500 和业务数字 1000+ 混在同一个错误码枚举中;客户端应依赖稳定的命名空间字符串。
|
|
830
|
+
|
|
831
|
+
## 3.3 不要把 Express Response 写死在 Filter
|
|
832
|
+
|
|
833
|
+
当前项目使用 Fastify,应通过 HttpAdapterHost 或明确的 Fastify 接口实现。
|
|
834
|
+
|
|
835
|
+
## 3.4 不要信任客户端 requestId
|
|
836
|
+
|
|
837
|
+
客户端值必须限制格式和长度;不符合规则时重新生成。
|
|
838
|
+
|
|
839
|
+
requestId 只能有一套实际生效的生成与上下文传播机制,避免中间件和 CLS 各自生成、造成同一请求出现两个 ID。
|
|
840
|
+
|
|
841
|
+
## 3.5 不要向客户端返回 stack
|
|
842
|
+
|
|
843
|
+
即使 development 环境也可能部署在共享测试服务器。stack、SQL、连接串和内部路径永远只进入受控日志。
|
|
844
|
+
|
|
845
|
+
## 3.6 不要记录原始数据库参数或完整 body
|
|
846
|
+
|
|
847
|
+
密码、Token、Cookie、Authorization、身份证件和业务 PII 都可能被写入日志。
|
|
848
|
+
|
|
849
|
+
## 3.7 不要同时维护 JWT 和 Redis Session 两套登录架构
|
|
850
|
+
|
|
851
|
+
当前代码已经选择 Opaque Redis Session。除非产品边界变化,否则先修好这一套,并把 JWT 文档标记为备选方案。
|
|
852
|
+
|
|
853
|
+
## 3.8 RBAC 不要默认放行
|
|
854
|
+
|
|
855
|
+
管理模块应默认拒绝。未声明权限的敏感路由不能自动允许所有登录用户。
|
|
856
|
+
|
|
857
|
+
## 3.9 不要让每个副本启动时自动跑迁移
|
|
858
|
+
|
|
859
|
+
多副本同时启动可能发生竞态。迁移应由单独发布 Job 执行。
|
|
860
|
+
|
|
861
|
+
## 3.10 不要因为参考项目功能多就全部实现
|
|
862
|
+
|
|
863
|
+
多租户、MFA、队列、GraphQL、WebSocket、Outbox 都应由真实产品需求驱动。
|
|
864
|
+
|
|
865
|
+
## 3.11 不要记录完整 ORM 参数和慢查询输入
|
|
866
|
+
|
|
867
|
+
慢查询日志可以记录 query name、耗时、表或受控摘要,不能默认保存 Prisma args、Drizzle 参数、原始 SQL 值或完整业务对象。
|
|
868
|
+
|
|
869
|
+
## 3.12 不要在应用模块加载后才初始化 OTel
|
|
870
|
+
|
|
871
|
+
自动插桩必须在 Nest、Fastify、HTTP、数据库客户端等应用模块之前加载。放在普通 Service 的 onModuleInit 中可能错过模块加载阶段。
|
|
872
|
+
|
|
873
|
+
## 3.13 不要直接复制不同技术栈的基础设施代码
|
|
874
|
+
|
|
875
|
+
参考仓库中的 Nest 版本、Express、Prisma、TypeORM 或其他适配代码不能原样搬入当前 NestJS 11 + Fastify + Drizzle 项目。应保留契约与边界,重新实现适配层。
|
|
876
|
+
|
|
877
|
+
---
|
|
878
|
+
|
|
879
|
+
# 4. 推荐施工顺序
|
|
880
|
+
|
|
881
|
+
## 阶段 A:立即止血
|
|
882
|
+
|
|
883
|
+
- [ ] S0-02 移除 DB/Redis 运行时测试接口。
|
|
884
|
+
- [ ] S0-03 轮换并移除已提交密钥。
|
|
885
|
+
- [ ] S0-01 修复 Session Lua。
|
|
886
|
+
- [ ] S0-04 修正生产依赖和启动命令。
|
|
887
|
+
- [ ] S0-05 提交数据库迁移。
|
|
888
|
+
|
|
889
|
+
交付标准:现有认证闭环真实可用,生产构建可以启动,不存在明显敏感接口。
|
|
890
|
+
|
|
891
|
+
## 阶段 B:建立安全基础设施
|
|
892
|
+
|
|
893
|
+
- [ ] S0-06 统一异常与 requestId。
|
|
894
|
+
- [ ] S0-07 登录限流与抗枚举。
|
|
895
|
+
- [ ] S1-01 配置校验。
|
|
896
|
+
- [ ] S1-02 数据库生命周期。
|
|
897
|
+
- [ ] S1-03 健康检查与停机。
|
|
898
|
+
- [ ] S1-04 结构化日志。
|
|
899
|
+
- [ ] S1-05 HTTP 安全。
|
|
900
|
+
- [ ] S1-09 自动化测试。
|
|
901
|
+
- [ ] S1-10 发布与 CI/CD。
|
|
902
|
+
- [ ] S1-11 最小指标与告警。
|
|
903
|
+
|
|
904
|
+
交付标准:可以部署到第一套受控测试环境,并能够定位问题、正确退出和安全失败。
|
|
905
|
+
|
|
906
|
+
## 阶段 C:形成管理后台
|
|
907
|
+
|
|
908
|
+
- [ ] S1-06 账号与 Session 生命周期。
|
|
909
|
+
- [ ] S1-07 最小授权内核。
|
|
910
|
+
- [ ] S1-08 响应与 OpenAPI 契约。
|
|
911
|
+
- [ ] S2-01 用户管理。
|
|
912
|
+
- [ ] S2-02 角色、权限和菜单。
|
|
913
|
+
- [ ] S2-04 审计。
|
|
914
|
+
|
|
915
|
+
交付标准:管理员与普通用户权限清晰,敏感操作可追踪。
|
|
916
|
+
|
|
917
|
+
## 阶段 D:按产品扩展
|
|
918
|
+
|
|
919
|
+
- [ ] 公司/部门/租户。
|
|
920
|
+
- [ ] 字典和系统配置。
|
|
921
|
+
- [ ] MinIO 文件模块。
|
|
922
|
+
- [ ] 队列与定时任务。
|
|
923
|
+
- [ ] 通知、导入导出和在线会话。
|
|
924
|
+
- [ ] 分布式追踪、Sentry、SSO 或 MFA。
|
|
925
|
+
|
|
926
|
+
---
|
|
927
|
+
|
|
928
|
+
# 5. 最终生产基线完成标准
|
|
929
|
+
|
|
930
|
+
下面是完成阶段 A、B、C 后的最终生产基线,不是要求阶段 A 单独满足所有条目。阶段 A/B/C 各自的交付条件以前一节为准;阶段 D 的可选功能只在实际实施时应用对应测试。
|
|
931
|
+
|
|
932
|
+
- [ ] 有数据库迁移,不只修改 schema.ts。
|
|
933
|
+
- [ ] 有单元测试和 Fastify 集成测试。
|
|
934
|
+
- [ ] 有权限与越权测试。
|
|
935
|
+
- [ ] 有失败场景和并发场景测试。
|
|
936
|
+
- [ ] 响应不泄露 passwordHash、Token、stack、SQL 或连接串。
|
|
937
|
+
- [ ] OpenAPI 与运行时响应一致。
|
|
938
|
+
- [ ] 日志包含 requestId,且完成脱敏。
|
|
939
|
+
- [ ] 生产依赖安装可以启动。
|
|
940
|
+
- [ ] readiness 在依赖故障时正确失败。
|
|
941
|
+
- [ ] SIGTERM 可以优雅关闭。
|
|
942
|
+
- [ ] 没有重新引入 HTTP 200 业务错误。
|
|
943
|
+
|
|
944
|
+
全部基础改造完成后,从项目根目录执行:
|
|
945
|
+
|
|
946
|
+
```powershell
|
|
947
|
+
vp install
|
|
948
|
+
vp run --filter shared build
|
|
949
|
+
vp check
|
|
950
|
+
vp run -r test
|
|
951
|
+
vp run -r build
|
|
952
|
+
vp run --filter server smoke
|
|
953
|
+
```
|
|
954
|
+
|
|
955
|
+
smoke 必须是有超时且会自行终止 Server 的脚本,不能直接把长期运行的 build:preview 当作 CI 验收命令。当前仓库尚无 smoke script;完成 S0-04、S1-03 和 S1-10 后再加入。
|
|
956
|
+
|
|
957
|
+
---
|
|
958
|
+
|
|
959
|
+
# 6. 当前最值得先建立的自动化测试
|
|
960
|
+
|
|
961
|
+
按收益排序:
|
|
962
|
+
|
|
963
|
+
1. Redis Lua create、replace、validate、touch、logout、revoke 集成测试。
|
|
964
|
+
2. 普通用户无法访问任何调试或管理接口。
|
|
965
|
+
3. 所有响应永不出现 passwordHash。
|
|
966
|
+
4. 登录不存在账号与错误密码的耗时和响应一致。
|
|
967
|
+
5. Session 失效返回 401,Redis 故障返回 503。
|
|
968
|
+
6. 统一异常契约和 requestId。
|
|
969
|
+
7. PostgreSQL 唯一约束、外键和连接故障映射。
|
|
970
|
+
8. 用户禁用、改密后全部 Session 失效。
|
|
971
|
+
9. RBAC 默认拒绝与跨公司越权。
|
|
972
|
+
10. 生产依赖镜像启动和 readiness。
|
|
973
|
+
|
|
974
|
+
---
|
|
975
|
+
|
|
976
|
+
# 7. 参考资料
|
|
977
|
+
|
|
978
|
+
- [buqiyuan/nest-admin](https://github.com/buqiyuan/nest-admin)
|
|
979
|
+
- [linlingqin77/Nest-Admin-Soybean](https://github.com/linlingqin77/Nest-Admin-Soybean)
|
|
980
|
+
- [NestJS Exception Filters](https://docs.nestjs.com/exception-filters)
|
|
981
|
+
- [NestJS Validation](https://docs.nestjs.com/techniques/validation)
|
|
982
|
+
- [NestJS Lifecycle Events](https://docs.nestjs.com/fundamentals/lifecycle-events)
|
|
983
|
+
- [NestJS Authorization](https://docs.nestjs.com/security/authorization)
|
|
984
|
+
- [NestJS Rate Limiting](https://docs.nestjs.com/security/rate-limiting)
|
|
985
|
+
- [RFC 9110](https://www.rfc-editor.org/rfc/rfc9110.html)
|
|
986
|
+
- [RFC 9457 Problem Details](https://www.rfc-editor.org/rfc/rfc9457.html)
|
|
987
|
+
- [OWASP Logging Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Logging_Cheat_Sheet.html)
|
|
988
|
+
- [OWASP Authentication Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Authentication_Cheat_Sheet.html)
|
|
989
|
+
- [PostgreSQL Error Codes](https://www.postgresql.org/docs/current/errcodes-appendix.html)
|
|
990
|
+
|
|
991
|
+
本清单的判断以当前源码为准。文档中已经设计但尚未进入 apps/server 的能力,仍然按“未实现”处理。
|