create-bubbles 0.1.26 → 0.1.28

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (575) hide show
  1. package/dist/index.js +4 -4
  2. package/package.json +10 -2
  3. package/template-pnpm-vp-monorepo/.changeset/README.md +8 -0
  4. package/template-pnpm-vp-monorepo/.changeset/config.json +11 -0
  5. package/template-pnpm-vp-monorepo/.gitattributes +5 -0
  6. package/template-pnpm-vp-monorepo/.github/workflows/ci.yml +33 -0
  7. package/template-pnpm-vp-monorepo/.github/workflows/docs.yml +55 -0
  8. package/template-pnpm-vp-monorepo/.github/workflows/release.yml +54 -0
  9. package/template-pnpm-vp-monorepo/.vite-hooks/commit-msg +1 -0
  10. package/template-pnpm-vp-monorepo/.vite-hooks/pre-commit +1 -0
  11. package/template-pnpm-vp-monorepo/.vite-hooks/run.mjs +17 -0
  12. package/template-pnpm-vp-monorepo/.vscode/settings.json +23 -0
  13. package/{LICENSE → template-pnpm-vp-monorepo/LICENSE} +2 -2
  14. package/template-pnpm-vp-monorepo/README.md +93 -0
  15. package/template-pnpm-vp-monorepo/_gitignore +43 -0
  16. package/template-pnpm-vp-monorepo/apps/docs/.vitepress/config.mts +69 -0
  17. package/template-pnpm-vp-monorepo/apps/docs/guide/getting-started.md +70 -0
  18. package/template-pnpm-vp-monorepo/apps/docs/guide/release.md +73 -0
  19. package/template-pnpm-vp-monorepo/apps/docs/guide/workspace.md +84 -0
  20. package/template-pnpm-vp-monorepo/apps/docs/index.md +22 -0
  21. package/template-pnpm-vp-monorepo/apps/docs/package.json +23 -0
  22. package/template-pnpm-vp-monorepo/apps/docs/tsconfig.json +7 -0
  23. package/template-pnpm-vp-monorepo/apps/docs/vite.config.ts +12 -0
  24. package/template-pnpm-vp-monorepo/apps/playground/index.html +14 -0
  25. package/template-pnpm-vp-monorepo/apps/playground/package.json +24 -0
  26. package/template-pnpm-vp-monorepo/apps/playground/src/App.vue +214 -0
  27. package/template-pnpm-vp-monorepo/apps/playground/src/env.d.ts +6 -0
  28. package/template-pnpm-vp-monorepo/apps/playground/src/main.ts +6 -0
  29. package/template-pnpm-vp-monorepo/apps/playground/src/style.css +728 -0
  30. package/template-pnpm-vp-monorepo/apps/playground/tsconfig.json +10 -0
  31. package/template-pnpm-vp-monorepo/apps/playground/vite.config.ts +29 -0
  32. package/template-pnpm-vp-monorepo/commitlint.config.mjs +3 -0
  33. package/template-pnpm-vp-monorepo/eslint.config.mjs +22 -0
  34. package/template-pnpm-vp-monorepo/mise.toml +3 -0
  35. package/template-pnpm-vp-monorepo/package.json +40 -0
  36. package/template-pnpm-vp-monorepo/packages/utils/LICENSE +21 -0
  37. package/template-pnpm-vp-monorepo/packages/utils/README.md +26 -0
  38. package/template-pnpm-vp-monorepo/packages/utils/_gitignore +4 -0
  39. package/template-pnpm-vp-monorepo/packages/utils/package.json +42 -0
  40. package/template-pnpm-vp-monorepo/packages/utils/scripts/verify-package.mjs +127 -0
  41. package/template-pnpm-vp-monorepo/packages/utils/src/index.ts +12 -0
  42. package/template-pnpm-vp-monorepo/packages/utils/tests/consumer/commonjs.cts +20 -0
  43. package/template-pnpm-vp-monorepo/packages/utils/tests/consumer/esm.mts +20 -0
  44. package/template-pnpm-vp-monorepo/packages/utils/tests/consumer/tsconfig.json +10 -0
  45. package/template-pnpm-vp-monorepo/packages/utils/tests/index.test.ts +30 -0
  46. package/template-pnpm-vp-monorepo/packages/utils/tsconfig.json +4 -0
  47. package/template-pnpm-vp-monorepo/packages/utils/vite.config.ts +20 -0
  48. package/template-pnpm-vp-monorepo/pnpm-workspace.yaml +27 -0
  49. package/template-pnpm-vp-monorepo/tsconfig/base.json +22 -0
  50. package/template-pnpm-vp-monorepo/tsconfig/node.json +8 -0
  51. package/template-pnpm-vp-monorepo/tsconfig/vue.json +7 -0
  52. package/template-pnpm-vp-monorepo/tsconfig.json +4 -0
  53. package/template-pnpm-vp-monorepo/vite.config.ts +38 -0
  54. package/template-vp-monorepo-react-nestjs/.agents/rules//345/205/261/344/272/253/344/273/243/347/240/201.md +2 -2
  55. package/template-vp-monorepo-react-nestjs/.agents/rules//351/234/200/346/261/202/344/270/216/350/256/276/350/256/241/346/226/207/346/241/243.md +50 -0
  56. package/template-vp-monorepo-react-nestjs/.codegraph/.gitignore +5 -0
  57. package/template-vp-monorepo-react-nestjs/.spaces/01./344/274/201/344/270/232/347/272/247/351/241/271/347/233/256/347/272/247//346/235/203/351/231/220/344/270/216/350/217/234/345/215/225/PRD.md +121 -0
  58. package/template-vp-monorepo-react-nestjs/.spaces/01./344/274/201/344/270/232/347/272/247/351/241/271/347/233/256/347/272/247//346/235/203/351/231/220/344/270/216/350/217/234/345/215/225/ui/cleanup-empty-preview.png +0 -0
  59. package/template-vp-monorepo-react-nestjs/.spaces/01./344/274/201/344/270/232/347/272/247/351/241/271/347/233/256/347/272/247//346/235/203/351/231/220/344/270/216/350/217/234/345/215/225/ui/company-created.png +0 -0
  60. package/template-vp-monorepo-react-nestjs/.spaces/01./344/274/201/344/270/232/347/272/247/351/241/271/347/233/256/347/272/247//346/235/203/351/231/220/344/270/216/350/217/234/345/215/225/ui/login-desktop.png +0 -0
  61. package/template-vp-monorepo-react-nestjs/.spaces/01./344/274/201/344/270/232/347/272/247/351/241/271/347/233/256/347/272/247//346/235/203/351/231/220/344/270/216/350/217/234/345/215/225/ui/member-role-assigned.png +0 -0
  62. package/template-vp-monorepo-react-nestjs/.spaces/01./344/274/201/344/270/232/347/272/247/351/241/271/347/233/256/347/272/247//346/235/203/351/231/220/344/270/216/350/217/234/345/215/225/ui/permission-revoked.png +0 -0
  63. package/template-vp-monorepo-react-nestjs/.spaces/01./344/274/201/344/270/232/347/272/247/351/241/271/347/233/256/347/272/247//346/235/203/351/231/220/344/270/216/350/217/234/345/215/225/ui/platform-menu-recovery.png +0 -0
  64. package/template-vp-monorepo-react-nestjs/.spaces/01./344/274/201/344/270/232/347/272/247/351/241/271/347/233/256/347/272/247//346/235/203/351/231/220/344/270/216/350/217/234/345/215/225/ui/project-created.png +0 -0
  65. package/template-vp-monorepo-react-nestjs/.spaces/01./344/274/201/344/270/232/347/272/247/351/241/271/347/233/256/347/272/247//346/235/203/351/231/220/344/270/216/350/217/234/345/215/225/ui/project-member-home.png +0 -0
  66. package/template-vp-monorepo-react-nestjs/.spaces/01./344/274/201/344/270/232/347/272/247/351/241/271/347/233/256/347/272/247//346/235/203/351/231/220/344/270/216/350/217/234/345/215/225/ui/replacement-administrator.png +0 -0
  67. package/template-vp-monorepo-react-nestjs/.spaces/01./344/274/201/344/270/232/347/272/247/351/241/271/347/233/256/347/272/247//346/235/203/351/231/220/344/270/216/350/217/234/345/215/225/ui/workspace-empty.png +0 -0
  68. package/template-vp-monorepo-react-nestjs/.spaces/01./344/274/201/344/270/232/347/272/247/351/241/271/347/233/256/347/272/247//346/235/203/351/231/220/344/270/216/350/217/234/345/215/225//345/206/263/347/255/226/350/256/260/345/275/225.md +29 -0
  69. package/template-vp-monorepo-react-nestjs/.spaces/01./344/274/201/344/270/232/347/272/247/351/241/271/347/233/256/347/272/247//346/235/203/351/231/220/344/270/216/350/217/234/345/215/225//345/211/215/347/253/257/344/272/244/346/216/245.md +74 -0
  70. package/template-vp-monorepo-react-nestjs/.spaces/01./344/274/201/344/270/232/347/272/247/351/241/271/347/233/256/347/272/247//346/235/203/351/231/220/344/270/216/350/217/234/345/215/225//345/220/216/347/253/257/346/265/213/350/257/225/346/212/245/345/221/212.md +115 -0
  71. package/template-vp-monorepo-react-nestjs/.spaces/01./344/274/201/344/270/232/347/272/247/351/241/271/347/233/256/347/272/247//346/235/203/351/231/220/344/270/216/350/217/234/345/215/225//346/212/200/346/234/257/345/245/221/347/272/246.md +580 -0
  72. package/template-vp-monorepo-react-nestjs/.spaces/01./344/274/201/344/270/232/347/272/247/351/241/271/347/233/256/347/272/247//346/235/203/351/231/220/344/270/216/350/217/234/345/215/225//346/265/213/350/257/225/346/212/245/345/221/212.md +137 -0
  73. package/template-vp-monorepo-react-nestjs/.spaces/01./344/274/201/344/270/232/347/272/247/351/241/271/347/233/256/347/272/247//346/235/203/351/231/220/344/270/216/350/217/234/345/215/225//346/265/213/350/257/225/350/257/201/346/215/256/browser.json +84 -0
  74. package/template-vp-monorepo-react-nestjs/.spaces/01./344/274/201/344/270/232/347/272/247/351/241/271/347/233/256/347/272/247//346/235/203/351/231/220/344/270/216/350/217/234/345/215/225//346/265/213/350/257/225/350/257/201/346/215/256/http.json +108 -0
  75. package/template-vp-monorepo-react-nestjs/.spaces/01./344/274/201/344/270/232/347/272/247/351/241/271/347/233/256/347/272/247//346/235/203/351/231/220/344/270/216/350/217/234/345/215/225//346/265/213/350/257/225/350/257/201/346/215/256/legacy-http.json +18 -0
  76. package/template-vp-monorepo-react-nestjs/.spaces/01./344/274/201/344/270/232/347/272/247/351/241/271/347/233/256/347/272/247//346/235/203/351/231/220/344/270/216/350/217/234/345/215/225//346/265/213/350/257/225/350/257/201/346/215/256/legacy.json +24 -0
  77. package/template-vp-monorepo-react-nestjs/.spaces/01./344/274/201/344/270/232/347/272/247/351/241/271/347/233/256/347/272/247//346/235/203/351/231/220/344/270/216/350/217/234/345/215/225//350/201/224/350/260/203/350/256/260/345/275/225.md +76 -0
  78. package/template-vp-monorepo-react-nestjs/.spaces/01./344/274/201/344/270/232/347/272/247/351/241/271/347/233/256/347/272/247//346/235/203/351/231/220/344/270/216/350/217/234/345/215/225//350/277/220/350/241/214/350/257/264/346/230/216.md +117 -0
  79. package/template-vp-monorepo-react-nestjs/.spaces/01./344/274/201/344/270/232/347/272/247/351/241/271/347/233/256/347/272/247//346/235/203/351/231/220/344/270/216/350/217/234/345/215/225//351/234/200/346/261/202/346/226/207/346/241/243.md +275 -0
  80. package/template-vp-monorepo-react-nestjs/.spaces/01./344/274/201/344/270/232/347/272/247/351/241/271/347/233/256/347/272/247//347/273/204/347/273/207/346/236/266/346/236/204//345/206/263/347/255/226/350/256/260/345/275/225.md +35 -0
  81. package/template-vp-monorepo-react-nestjs/.spaces/01./344/274/201/344/270/232/347/272/247/351/241/271/347/233/256/347/272/247//347/273/204/347/273/207/346/236/266/346/236/204//346/212/200/346/234/257/345/245/221/347/272/246.md +744 -0
  82. package/template-vp-monorepo-react-nestjs/.spaces/01./344/274/201/344/270/232/347/272/247/351/241/271/347/233/256/347/272/247//347/273/204/347/273/207/346/236/266/346/236/204//346/265/213/350/257/225/346/212/245/345/221/212.md +174 -0
  83. package/template-vp-monorepo-react-nestjs/.spaces/01./344/274/201/344/270/232/347/272/247/351/241/271/347/233/256/347/272/247//347/273/204/347/273/207/346/236/266/346/236/204//350/201/224/350/260/203/350/256/260/345/275/225.md +137 -0
  84. package/template-vp-monorepo-react-nestjs/.spaces/01./344/274/201/344/270/232/347/272/247/351/241/271/347/233/256/347/272/247//347/273/204/347/273/207/346/236/266/346/236/204//350/256/276/350/256/241/346/226/271/346/241/210.md +215 -0
  85. package/template-vp-monorepo-react-nestjs/.spaces/01./344/274/201/344/270/232/347/272/247/351/241/271/347/233/256/347/272/247//347/273/204/347/273/207/346/236/266/346/236/204//351/234/200/346/261/202/346/226/207/346/241/243.md +421 -0
  86. package/template-vp-monorepo-react-nestjs/.spaces/{server/05./344/270/212/344/274/240/346/224/271/351/200/240/346/226/271/346/241/210/README.md → 02./344/270/212/344/274/240/344/270/216/346/226/207/344/273/266//344/270/212/344/274/240/346/224/271/351/200/240//350/256/276/350/256/241/346/226/271/346/241/210.md} +13 -20
  87. package/template-vp-monorepo-react-nestjs/.spaces/{server/06./345/205/254/345/205/261/351/230/237/345/210/227/346/216/245/345/205/245/346/226/271/346/241/210//344/270/212/344/274/240/346/270/205/347/220/206.md → 02./344/270/212/344/274/240/344/270/216/346/226/207/344/273/266//344/270/212/344/274/240/346/270/205/347/220/206//350/256/276/350/256/241/346/226/271/346/241/210.md} +13 -8
  88. package/template-vp-monorepo-react-nestjs/.spaces/{server/04.upload.md → 02./344/270/212/344/274/240/344/270/216/346/226/207/344/273/266//345/210/206/347/211/207/344/270/212/344/274/240//345/256/236/346/226/275/346/225/231/347/250/213.md} +21 -18
  89. package/template-vp-monorepo-react-nestjs/.spaces/{server/06./345/205/254/345/205/261/351/230/237/345/210/227/346/216/245/345/205/245/346/226/271/346/241/210/README.md → 03./344/273/273/345/212/241/351/230/237/345/210/227//345/205/254/345/205/261/351/230/237/345/210/227//350/256/276/350/256/241/346/226/271/346/241/210.md} +13 -6
  90. package/template-vp-monorepo-react-nestjs/.spaces/04./347/225/214/351/235/242/344/270/216/344/270/273/351/242/230//344/270/207/347/211/251/346/242/246/345/271/273/ui/accounts-mobile-320.png +0 -0
  91. package/template-vp-monorepo-react-nestjs/.spaces/04./347/225/214/351/235/242/344/270/216/344/270/273/351/242/230//344/270/207/347/211/251/346/242/246/345/271/273/ui/accounts-mobile-360.png +0 -0
  92. package/template-vp-monorepo-react-nestjs/.spaces/04./347/225/214/351/235/242/344/270/216/344/270/273/351/242/230//344/270/207/347/211/251/346/242/246/345/271/273/ui/accounts-mobile-390.png +0 -0
  93. package/template-vp-monorepo-react-nestjs/.spaces/04./347/225/214/351/235/242/344/270/216/344/270/273/351/242/230//344/270/207/347/211/251/346/242/246/345/271/273/ui/companies-desktop-data.png +0 -0
  94. package/template-vp-monorepo-react-nestjs/.spaces/04./347/225/214/351/235/242/344/270/216/344/270/273/351/242/230//344/270/207/347/211/251/346/242/246/345/271/273/ui/companies-desktop-empty.png +0 -0
  95. package/template-vp-monorepo-react-nestjs/.spaces/04./347/225/214/351/235/242/344/270/216/344/270/273/351/242/230//344/270/207/347/211/251/346/242/246/345/271/273/ui/companies-mobile-320.png +0 -0
  96. package/template-vp-monorepo-react-nestjs/.spaces/04./347/225/214/351/235/242/344/270/216/344/270/273/351/242/230//344/270/207/347/211/251/346/242/246/345/271/273/ui/companies-mobile-360.png +0 -0
  97. package/template-vp-monorepo-react-nestjs/.spaces/04./347/225/214/351/235/242/344/270/216/344/270/273/351/242/230//344/270/207/347/211/251/346/242/246/345/271/273/ui/companies-mobile-390.png +0 -0
  98. package/template-vp-monorepo-react-nestjs/.spaces/04./347/225/214/351/235/242/344/270/216/344/270/273/351/242/230//344/270/207/347/211/251/346/242/246/345/271/273/ui/company-create-dialog.png +0 -0
  99. package/template-vp-monorepo-react-nestjs/.spaces/04./347/225/214/351/235/242/344/270/216/344/270/273/351/242/230//344/270/207/347/211/251/346/242/246/345/271/273/ui/company-projects-1440.png +0 -0
  100. package/template-vp-monorepo-react-nestjs/.spaces/04./347/225/214/351/235/242/344/270/216/344/270/273/351/242/230//344/270/207/347/211/251/346/242/246/345/271/273/ui/company-projects-390.png +0 -0
  101. package/template-vp-monorepo-react-nestjs/.spaces/04./347/225/214/351/235/242/344/270/216/344/270/273/351/242/230//344/270/207/347/211/251/346/242/246/345/271/273/ui/login-1440.png +0 -0
  102. package/template-vp-monorepo-react-nestjs/.spaces/04./347/225/214/351/235/242/344/270/216/344/270/273/351/242/230//344/270/207/347/211/251/346/242/246/345/271/273/ui/login-390.png +0 -0
  103. package/template-vp-monorepo-react-nestjs/.spaces/04./347/225/214/351/235/242/344/270/216/344/270/273/351/242/230//344/270/207/347/211/251/346/242/246/345/271/273/ui/project-home-1440.png +0 -0
  104. package/template-vp-monorepo-react-nestjs/.spaces/04./347/225/214/351/235/242/344/270/216/344/270/273/351/242/230//344/270/207/347/211/251/346/242/246/345/271/273/ui/project-home-390.png +0 -0
  105. package/template-vp-monorepo-react-nestjs/.spaces/04./347/225/214/351/235/242/344/270/216/344/270/273/351/242/230//344/270/207/347/211/251/346/242/246/345/271/273/ui/register-1440.png +0 -0
  106. package/template-vp-monorepo-react-nestjs/.spaces/04./347/225/214/351/235/242/344/270/216/344/270/273/351/242/230//344/270/207/347/211/251/346/242/246/345/271/273/ui/register-390.png +0 -0
  107. package/template-vp-monorepo-react-nestjs/.spaces/04./347/225/214/351/235/242/344/270/216/344/270/273/351/242/230//344/270/207/347/211/251/346/242/246/345/271/273/ui/workspaces-1440.png +0 -0
  108. package/template-vp-monorepo-react-nestjs/.spaces/04./347/225/214/351/235/242/344/270/216/344/270/273/351/242/230//344/270/207/347/211/251/346/242/246/345/271/273/ui/workspaces-390.png +0 -0
  109. package/template-vp-monorepo-react-nestjs/.spaces/04./347/225/214/351/235/242/344/270/216/344/270/273/351/242/230//344/270/207/347/211/251/346/242/246/345/271/273/ui/workspaces-empty.png +0 -0
  110. package/template-vp-monorepo-react-nestjs/.spaces/04./347/225/214/351/235/242/344/270/216/344/270/273/351/242/230//344/270/207/347/211/251/346/242/246/345/271/273//345/267/245/345/205/267/fixtures.mjs +132 -0
  111. package/template-vp-monorepo-react-nestjs/.spaces/04./347/225/214/351/235/242/344/270/216/344/270/273/351/242/230//344/270/207/347/211/251/346/242/246/345/271/273//345/267/245/345/205/267/visual-check.mjs +274 -0
  112. package/template-vp-monorepo-react-nestjs/.spaces/04./347/225/214/351/235/242/344/270/216/344/270/273/351/242/230//344/270/207/347/211/251/346/242/246/345/271/273//346/265/213/350/257/225/350/257/201/346/215/256/visual-report.json +104 -0
  113. package/template-vp-monorepo-react-nestjs/.spaces/04./347/225/214/351/235/242/344/270/216/344/270/273/351/242/230//344/270/207/347/211/251/346/242/246/345/271/273//351/252/214/350/257/201/350/257/264/346/230/216.md +25 -0
  114. package/template-vp-monorepo-react-nestjs/.spaces/04./347/225/214/351/235/242/344/270/216/344/270/273/351/242/230//345/233/275/351/231/205/345/214/226//344/272/244/344/273/230/350/256/260/345/275/225.md +21 -0
  115. package/template-vp-monorepo-react-nestjs/.spaces/04./347/225/214/351/235/242/344/270/216/344/270/273/351/242/230//345/233/275/351/231/205/345/214/226//345/217/221/345/270/203/350/257/204/344/274/260.md +93 -0
  116. package/template-vp-monorepo-react-nestjs/.spaces/04./347/225/214/351/235/242/344/270/216/344/270/273/351/242/230//345/233/275/351/231/205/345/214/226//345/267/245/345/205/267//350/277/220/350/241/214/346/227/266/345/217/221/345/270/203/346/243/200/346/237/245.mjs +340 -0
  117. package/template-vp-monorepo-react-nestjs/.spaces/04./347/225/214/351/235/242/344/270/216/344/270/273/351/242/230//345/233/275/351/231/205/345/214/226//346/265/213/350/257/225/346/212/245/345/221/212.md +41 -0
  118. package/template-vp-monorepo-react-nestjs/.spaces/04./347/225/214/351/235/242/344/270/216/344/270/273/351/242/230//345/233/275/351/231/205/345/214/226//346/265/213/350/257/225/350/257/201/346/215/256/cli-/346/211/253/346/217/217/350/276/271/347/225/214/comment-clean/catalog/en_US.json +4 -0
  119. package/template-vp-monorepo-react-nestjs/.spaces/04./347/225/214/351/235/242/344/270/216/344/270/273/351/242/230//345/233/275/351/231/205/345/214/226//346/265/213/350/257/225/350/257/201/346/215/256/cli-/346/211/253/346/217/217/350/276/271/347/225/214/comment-clean/i18n.config.mjs +9 -0
  120. package/template-vp-monorepo-react-nestjs/.spaces/04./347/225/214/351/235/242/344/270/216/344/270/273/351/242/230//345/233/275/351/231/205/345/214/226//346/265/213/350/257/225/350/257/201/346/215/256/cli-/346/211/253/346/217/217/350/276/271/347/225/214/comment-clean/report.json +16 -0
  121. package/template-vp-monorepo-react-nestjs/.spaces/04./347/225/214/351/235/242/344/270/216/344/270/273/351/242/230//345/233/275/351/231/205/345/214/226//346/265/213/350/257/225/350/257/201/346/215/256/cli-/346/211/253/346/217/217/350/276/271/347/225/214/comment-clean/source/app.ts +2 -0
  122. package/template-vp-monorepo-react-nestjs/.spaces/04./347/225/214/351/235/242/344/270/216/344/270/273/351/242/230//345/233/275/351/231/205/345/214/226//346/265/213/350/257/225/350/257/201/346/215/256/cli-/346/211/253/346/217/217/350/276/271/347/225/214/empty-scan/catalog/en_US.json +4 -0
  123. package/template-vp-monorepo-react-nestjs/.spaces/04./347/225/214/351/235/242/344/270/216/344/270/273/351/242/230//345/233/275/351/231/205/345/214/226//346/265/213/350/257/225/350/257/201/346/215/256/cli-/346/211/253/346/217/217/350/276/271/347/225/214/empty-scan/i18n.config.mjs +9 -0
  124. package/template-vp-monorepo-react-nestjs/.spaces/04./347/225/214/351/235/242/344/270/216/344/270/273/351/242/230//345/233/275/351/231/205/345/214/226//346/265/213/350/257/225/350/257/201/346/215/256/cli-/346/211/253/346/217/217/350/276/271/347/225/214/empty-scan/report.json +19 -0
  125. package/template-vp-monorepo-react-nestjs/.spaces/04./347/225/214/351/235/242/344/270/216/344/270/273/351/242/230//345/233/275/351/231/205/345/214/226//346/265/213/350/257/225/350/257/201/346/215/256/cli-/346/211/253/346/217/217/350/276/271/347/225/214/output.json +84 -0
  126. package/template-vp-monorepo-react-nestjs/.spaces/04./347/225/214/351/235/242/344/270/216/344/270/273/351/242/230//345/233/275/351/231/205/345/214/226//346/265/213/350/257/225/350/257/201/346/215/256/cli-/346/211/253/346/217/217/350/276/271/347/225/214//345/275/223/345/211/215/345/244/215/351/252/214.json +86 -0
  127. package/template-vp-monorepo-react-nestjs/.spaces/04./347/225/214/351/235/242/344/270/216/344/270/273/351/242/230//345/233/275/351/231/205/345/214/226//346/265/213/350/257/225/350/257/201/346/215/256/cli-/346/211/253/346/217/217/350/276/271/347/225/214//346/243/200/346/237/245/347/273/223/346/236/234.json +30 -0
  128. package/template-vp-monorepo-react-nestjs/.spaces/04./347/225/214/351/235/242/344/270/216/344/270/273/351/242/230//345/233/275/351/231/205/345/214/226//346/265/213/350/257/225/350/257/201/346/215/256/cli-/346/211/253/346/217/217/350/276/271/347/225/214//346/263/250/351/207/212/345/233/236/345/275/222.json +40 -0
  129. package/template-vp-monorepo-react-nestjs/.spaces/04./347/225/214/351/235/242/344/270/216/344/270/273/351/242/230//345/233/275/351/231/205/345/214/226//346/265/213/350/257/225/350/257/201/346/215/256//345/214/205/345/217/221/345/270/203/bubblesjs-i18n-core-0.0.0.tgz +0 -0
  130. package/template-vp-monorepo-react-nestjs/.spaces/04./347/225/214/351/235/242/344/270/216/344/270/273/351/242/230//345/233/275/351/231/205/345/214/226//346/265/213/350/257/225/350/257/201/346/215/256//345/214/205/345/217/221/345/270/203/bubblesjs-i18n-react-0.0.0.tgz +0 -0
  131. package/template-vp-monorepo-react-nestjs/.spaces/04./347/225/214/351/235/242/344/270/216/344/270/273/351/242/230//345/233/275/351/231/205/345/214/226//346/265/213/350/257/225/350/257/201/346/215/256//345/214/205/345/217/221/345/270/203/bubblesjs-i18n-vue-0.0.1.tgz +0 -0
  132. package/template-vp-monorepo-react-nestjs/.spaces/04./347/225/214/351/235/242/344/270/216/344/270/273/351/242/230//345/233/275/351/231/205/345/214/226//346/265/213/350/257/225/350/257/201/346/215/256//345/214/205/345/217/221/345/270/203//344/272/247/347/211/251/345/244/215/351/252/214.json +419 -0
  133. package/template-vp-monorepo-react-nestjs/.spaces/04./347/225/214/351/235/242/344/270/216/344/270/273/351/242/230//345/233/275/351/231/205/345/214/226//346/265/213/350/257/225/350/257/201/346/215/256//345/214/205/345/217/221/345/270/203//346/243/200/346/237/245/347/273/223/346/236/234.json +339 -0
  134. package/template-vp-monorepo-react-nestjs/.spaces/04./347/225/214/351/235/242/344/270/216/344/270/273/351/242/230//345/233/275/351/231/205/345/214/226//346/265/213/350/257/225/350/257/201/346/215/256//350/277/220/350/241/214/346/227/266/345/217/221/345/270/203/346/243/200/346/237/245.json +131 -0
  135. package/template-vp-monorepo-react-nestjs/.spaces/04./347/225/214/351/235/242/344/270/216/344/270/273/351/242/230//345/233/275/351/231/205/345/214/226//350/256/276/350/256/241/346/226/271/346/241/210.md +37 -0
  136. package/template-vp-monorepo-react-nestjs/.spaces/04./347/225/214/351/235/242/344/270/216/344/270/273/351/242/230//345/233/275/351/231/205/345/214/226//351/234/200/346/261/202/346/226/207/346/241/243.md +42 -0
  137. package/template-vp-monorepo-react-nestjs/.spaces/05./350/277/220/350/241/214/347/273/264/346/212/244//345/271/263/345/217/260/346/223/215/344/275/234/346/211/213/345/206/214.md +397 -0
  138. package/template-vp-monorepo-react-nestjs/.spaces/05./350/277/220/350/241/214/347/273/264/346/212/244//346/225/260/346/215/256/345/272/223/350/277/201/347/247/273//345/244/207/344/273/275/backup.dump +0 -0
  139. package/template-vp-monorepo-react-nestjs/.spaces/05./350/277/220/350/241/214/347/273/264/346/212/244//346/225/260/346/215/256/345/272/223/350/277/201/347/247/273//345/244/207/344/273/275/export-dump.ps1 +34 -0
  140. package/template-vp-monorepo-react-nestjs/.spaces/05./350/277/220/350/241/214/347/273/264/346/212/244//346/225/260/346/215/256/345/272/223/350/277/201/347/247/273//345/244/207/344/273/275/restore-dump.ps1 +73 -0
  141. package/template-vp-monorepo-react-nestjs/.spaces/05./350/277/220/350/241/214/347/273/264/346/212/244//346/225/260/346/215/256/345/272/223/350/277/201/347/247/273//346/223/215/344/275/234/346/214/207/345/215/227.md +227 -0
  142. package/template-vp-monorepo-react-nestjs/.spaces/05./350/277/220/350/241/214/347/273/264/346/212/244//346/225/260/346/215/256/345/272/223/350/277/201/347/247/273//351/234/200/346/261/202/346/226/207/346/241/243.md +31 -0
  143. package/template-vp-monorepo-react-nestjs/.spaces/06./350/256/244/350/257/201/344/270/216/344/274/232/350/257/235//344/274/232/350/257/235/347/256/241/347/220/206//346/212/200/346/234/257/345/245/221/347/272/246.md +96 -0
  144. package/template-vp-monorepo-react-nestjs/.spaces/06./350/256/244/350/257/201/344/270/216/344/274/232/350/257/235//344/274/232/350/257/235/347/256/241/347/220/206//351/234/200/346/261/202/346/226/207/346/241/243.md +88 -0
  145. package/template-vp-monorepo-react-nestjs/.spaces/06./350/256/244/350/257/201/344/270/216/344/274/232/350/257/235//344/277/256/346/224/271/345/257/206/347/240/201/PRD.md +56 -0
  146. package/template-vp-monorepo-react-nestjs/.spaces/06./350/256/244/350/257/201/344/270/216/344/274/232/350/257/235//344/277/256/346/224/271/345/257/206/347/240/201//346/212/200/346/234/257/345/245/221/347/272/246.md +93 -0
  147. package/template-vp-monorepo-react-nestjs/.spaces/06./350/256/244/350/257/201/344/270/216/344/274/232/350/257/235//344/277/256/346/224/271/345/257/206/347/240/201//346/265/213/350/257/225/346/212/245/345/221/212.md +41 -0
  148. package/template-vp-monorepo-react-nestjs/.spaces/06./350/256/244/350/257/201/344/270/216/344/274/232/350/257/235//344/277/256/346/224/271/345/257/206/347/240/201//350/201/224/350/260/203/350/256/260/345/275/225.md +27 -0
  149. package/template-vp-monorepo-react-nestjs/.spaces/06./350/256/244/350/257/201/344/270/216/344/274/232/350/257/235//344/277/256/346/224/271/345/257/206/347/240/201//350/256/276/350/256/241/346/226/271/346/241/210.md +54 -0
  150. package/template-vp-monorepo-react-nestjs/.spaces/06./350/256/244/350/257/201/344/270/216/344/274/232/350/257/235//344/277/256/346/224/271/345/257/206/347/240/201//351/234/200/346/261/202/346/226/207/346/241/243.md +64 -0
  151. package/template-vp-monorepo-react-nestjs/.spaces/07.API/344/270/216/351/224/231/350/257/257//346/212/200/346/234/257/345/245/221/347/272/246.md +95 -0
  152. package/template-vp-monorepo-react-nestjs/.spaces/README.md +86 -0
  153. package/template-vp-monorepo-react-nestjs/.spaces//346/226/207/346/241/243/350/247/204/350/214/203.md +97 -0
  154. package/template-vp-monorepo-react-nestjs/AGENTS.md +12 -0
  155. package/template-vp-monorepo-react-nestjs/README.md +3 -27
  156. package/template-vp-monorepo-react-nestjs/apps/server/drizzle/0002_enterprise_access.sql +182 -0
  157. package/template-vp-monorepo-react-nestjs/apps/server/drizzle/0003_cute_killmonger.sql +357 -0
  158. package/template-vp-monorepo-react-nestjs/apps/server/drizzle/0004_company-member-invitations.sql +25 -0
  159. package/template-vp-monorepo-react-nestjs/apps/server/drizzle/0005_menu_svg_icons.sql +54 -0
  160. package/template-vp-monorepo-react-nestjs/apps/server/drizzle/meta/0002_snapshot.json +1801 -0
  161. package/template-vp-monorepo-react-nestjs/apps/server/drizzle/meta/0003_snapshot.json +3511 -0
  162. package/template-vp-monorepo-react-nestjs/apps/server/drizzle/meta/0004_snapshot.json +3713 -0
  163. package/template-vp-monorepo-react-nestjs/apps/server/drizzle/meta/_journal.json +29 -1
  164. package/template-vp-monorepo-react-nestjs/apps/server/drizzle/rollback/0003_organization_backfill.sql +32 -0
  165. package/template-vp-monorepo-react-nestjs/apps/server/package.json +6 -4
  166. package/template-vp-monorepo-react-nestjs/apps/server/src/access-init.ts +45 -0
  167. package/template-vp-monorepo-react-nestjs/apps/server/src/app.controller.ts +3 -0
  168. package/template-vp-monorepo-react-nestjs/apps/server/src/app.module.ts +28 -5
  169. package/template-vp-monorepo-react-nestjs/apps/server/src/app.service.ts +3 -0
  170. package/template-vp-monorepo-react-nestjs/apps/server/src/common/adapters/fastify.adapter.ts +11 -0
  171. package/template-vp-monorepo-react-nestjs/apps/server/src/common/constants/session.constants.ts +9 -0
  172. package/template-vp-monorepo-react-nestjs/apps/server/src/common/decorators/access-policy.decorator.ts +18 -0
  173. package/template-vp-monorepo-react-nestjs/apps/server/src/common/decorators/current-auth.decorator.ts +4 -0
  174. package/template-vp-monorepo-react-nestjs/apps/server/src/common/decorators/public.decorator.ts +3 -0
  175. package/template-vp-monorepo-react-nestjs/apps/server/src/common/exceptions/app.exception.ts +9 -0
  176. package/template-vp-monorepo-react-nestjs/apps/server/src/common/filters/global-exception.filter.ts +38 -5
  177. package/template-vp-monorepo-react-nestjs/apps/server/src/common/security/password-security-event.ts +98 -0
  178. package/template-vp-monorepo-react-nestjs/apps/server/src/config/app.config.ts +3 -0
  179. package/template-vp-monorepo-react-nestjs/apps/server/src/config/database.config.ts +3 -0
  180. package/template-vp-monorepo-react-nestjs/apps/server/src/config/llm.config.ts +3 -0
  181. package/template-vp-monorepo-react-nestjs/apps/server/src/config/queue.config.ts +14 -0
  182. package/template-vp-monorepo-react-nestjs/apps/server/src/config/redis.config.ts +3 -0
  183. package/template-vp-monorepo-react-nestjs/apps/server/src/config/session.config.ts +7 -0
  184. package/template-vp-monorepo-react-nestjs/apps/server/src/config/storage.config.ts +9 -0
  185. package/template-vp-monorepo-react-nestjs/apps/server/src/database/access.schema.ts +394 -0
  186. package/template-vp-monorepo-react-nestjs/apps/server/src/database/db.module.ts +3 -0
  187. package/template-vp-monorepo-react-nestjs/apps/server/src/database/organization.schema.ts +453 -0
  188. package/template-vp-monorepo-react-nestjs/apps/server/src/database/schema.ts +6 -0
  189. package/template-vp-monorepo-react-nestjs/apps/server/src/main.ts +4 -0
  190. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/access/access-http.ts +29 -0
  191. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/access/access.errors.ts +130 -0
  192. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/access/access.guard.ts +63 -0
  193. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/access/access.module.ts +27 -0
  194. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/access/access.service.ts +441 -0
  195. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/access/access.store.ts +68 -0
  196. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/access/access.validation.ts +44 -0
  197. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/access/maintenance/permissions-cleanup.controller.ts +27 -0
  198. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/access/maintenance/permissions-cleanup.service.ts +260 -0
  199. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/access/maintenance/permissions-cleanup.validation.ts +7 -0
  200. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/access/roles/roles.controller.ts +80 -0
  201. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/access/roles/roles.service.ts +249 -0
  202. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/access/roles/roles.validation.ts +24 -0
  203. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/access/seed/access-seed.service.ts +183 -0
  204. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/access/workspaces/workspaces.controller.ts +28 -0
  205. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/access/workspaces/workspaces.service.ts +94 -0
  206. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/access/workspaces/workspaces.validation.ts +5 -0
  207. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/audit/audit.controller.ts +26 -0
  208. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/audit/audit.module.ts +11 -0
  209. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/audit/audit.service.ts +74 -0
  210. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/audit/audit.validation.ts +11 -0
  211. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/auth/auth.controller.ts +25 -0
  212. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/auth/auth.errors.ts +10 -0
  213. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/auth/auth.module.ts +1 -1
  214. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/auth/auth.repository.ts +60 -0
  215. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/auth/auth.service.ts +69 -11
  216. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/auth/dto/register.dto.ts +1 -1
  217. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/auth/guards/session-auth.guard.ts +8 -0
  218. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/auth/password/change-password.dto.ts +17 -0
  219. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/auth/password.service.ts +6 -0
  220. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/auth/session/session-store.service.ts +46 -0
  221. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/auth/session/session-token.service.ts +12 -0
  222. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/auth/session/session.script.ts +7 -1
  223. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/companies/companies.controller.ts +105 -0
  224. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/companies/companies.module.ts +12 -0
  225. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/companies/companies.service.ts +523 -0
  226. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/members/accounts/accounts.controller.ts +72 -0
  227. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/members/accounts/accounts.service.ts +154 -0
  228. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/members/accounts/accounts.validation.ts +8 -0
  229. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/members/accounts/password-reset/password-reset.service.ts +81 -0
  230. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/members/accounts/password-reset/reset-password.validation.ts +13 -0
  231. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/members/administrators/administrators.service.ts +116 -0
  232. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/members/administrators/administrators.validation.ts +1 -0
  233. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/members/invitations/company-member-invitations.controller.ts +69 -0
  234. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/members/invitations/member-invitation-acceptance.controller.ts +23 -0
  235. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/members/invitations/member-invitations.service.ts +344 -0
  236. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/members/invitations/member-invitations.validation.ts +23 -0
  237. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/members/members.controller.ts +88 -0
  238. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/members/members.module.ts +31 -0
  239. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/members/members.service.ts +573 -0
  240. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/members/members.validation.ts +19 -0
  241. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/menus/menus.controller.ts +56 -0
  242. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/menus/menus.module.ts +11 -0
  243. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/menus/menus.service.ts +230 -0
  244. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/menus/menus.validation.ts +30 -0
  245. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/organization/candidates/global-account/global-account-candidates.controller.ts +35 -0
  246. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/organization/candidates/global-account/global-account-candidates.service.ts +109 -0
  247. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/organization/candidates/member-candidates.controller.ts +60 -0
  248. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/organization/candidates/member-candidates.service.ts +939 -0
  249. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/organization/initialization/project-organization-initialization.service.ts +189 -0
  250. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/organization/organization.module.ts +34 -0
  251. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/organization/organization.store.ts +150 -0
  252. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/organization/organization.validation.ts +23 -0
  253. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/organization/positions/positions.controller.ts +160 -0
  254. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/organization/positions/positions.service.ts +636 -0
  255. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/organization/templates/organization-templates.controller.ts +77 -0
  256. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/organization/templates/organization-templates.service.ts +501 -0
  257. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/organization/templates/organization-templates.store.ts +163 -0
  258. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/organization/units/organization-units.controller.ts +187 -0
  259. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/organization/units/organization-units.service.ts +947 -0
  260. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/projects/projects.controller.ts +94 -0
  261. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/projects/projects.module.ts +13 -0
  262. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/projects/projects.service.ts +369 -0
  263. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/task-queue/queue-worker.bootstrap.ts +3 -0
  264. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/task-queue/task-queue.contracts.ts +4 -0
  265. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/task-queue/task-queue.module.ts +5 -0
  266. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/task-queue/task-queue.processor.ts +13 -0
  267. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/task-queue/task-queue.service.ts +9 -0
  268. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/test/db/db.controller.ts +9 -0
  269. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/test/db/db.service.ts +9 -0
  270. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/test/redis/redis.controller.ts +9 -0
  271. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/test/redis/redis.service.ts +18 -0
  272. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/upload/dto/upload-params.dto.ts +1 -1
  273. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/upload/storage/exact-size.transform.ts +14 -3
  274. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/upload/storage/minio-storage.adapter.ts +37 -0
  275. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/upload/storage/storage.port.ts +21 -0
  276. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/upload/upload.constants.ts +9 -0
  277. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/upload/upload.controller.ts +25 -0
  278. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/upload/upload.reponsitory.ts +27 -0
  279. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/upload/upload.service.ts +78 -0
  280. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/upload/utils/object-key.ts +4 -0
  281. package/template-vp-monorepo-react-nestjs/apps/server/src/utils/server-address.ts +6 -0
  282. package/template-vp-monorepo-react-nestjs/apps/server/test/access/access-policy.spec.ts +95 -0
  283. package/template-vp-monorepo-react-nestjs/apps/server/test/access/access.integration.spec.ts +2250 -0
  284. package/template-vp-monorepo-react-nestjs/apps/server/test/access/member-onboarding.validation.spec.ts +78 -0
  285. package/template-vp-monorepo-react-nestjs/apps/server/test/auth/password/password-operations.spec.ts +433 -0
  286. package/template-vp-monorepo-react-nestjs/apps/server/test/auth/password/password.integration.spec.ts +300 -0
  287. package/template-vp-monorepo-react-nestjs/apps/server/test/error-catalog.spec.ts +6 -1
  288. package/template-vp-monorepo-react-nestjs/apps/server/test/menus.validation.spec.ts +28 -0
  289. package/template-vp-monorepo-react-nestjs/apps/server/test/organization/organization-domain.spec.ts +260 -0
  290. package/template-vp-monorepo-react-nestjs/apps/server/tsconfig.scripts.json +5 -0
  291. package/template-vp-monorepo-react-nestjs/apps/web/.agents/rules//347/273/204/344/273/266/345/244/215/347/224/250.md +7 -0
  292. package/template-vp-monorepo-react-nestjs/apps/web/.agents/rules//350/241/250/345/215/225/345/233/236/345/241/253.md +4 -0
  293. package/template-vp-monorepo-react-nestjs/apps/web/AGENTS.md +17 -8
  294. package/template-vp-monorepo-react-nestjs/apps/web/README.MD +36 -8
  295. package/template-vp-monorepo-react-nestjs/apps/web/index.html +2 -2
  296. package/template-vp-monorepo-react-nestjs/apps/web/package.json +1 -0
  297. package/template-vp-monorepo-react-nestjs/apps/web/src/App.tsx +19 -8
  298. package/template-vp-monorepo-react-nestjs/apps/web/src/api/auth.ts +14 -1
  299. package/template-vp-monorepo-react-nestjs/apps/web/src/assets/svg/accounts.svg +4 -0
  300. package/template-vp-monorepo-react-nestjs/apps/web/src/assets/svg/audit-log.svg +4 -0
  301. package/template-vp-monorepo-react-nestjs/apps/web/src/assets/svg/companies.svg +5 -0
  302. package/template-vp-monorepo-react-nestjs/apps/web/src/assets/svg/dashboard.svg +6 -0
  303. package/template-vp-monorepo-react-nestjs/apps/web/src/assets/svg/home.svg +4 -0
  304. package/template-vp-monorepo-react-nestjs/apps/web/src/assets/svg/members.svg +4 -0
  305. package/template-vp-monorepo-react-nestjs/apps/web/src/assets/svg/menu-item.svg +4 -0
  306. package/template-vp-monorepo-react-nestjs/apps/web/src/assets/svg/menus.svg +6 -0
  307. package/template-vp-monorepo-react-nestjs/apps/web/src/assets/svg/organization-template.svg +4 -0
  308. package/template-vp-monorepo-react-nestjs/apps/web/src/assets/svg/organization.svg +6 -0
  309. package/template-vp-monorepo-react-nestjs/apps/web/src/assets/svg/positions.svg +4 -0
  310. package/template-vp-monorepo-react-nestjs/apps/web/src/assets/svg/profile.svg +5 -0
  311. package/template-vp-monorepo-react-nestjs/apps/web/src/assets/svg/projects.svg +4 -0
  312. package/template-vp-monorepo-react-nestjs/apps/web/src/assets/svg/roles.svg +4 -0
  313. package/template-vp-monorepo-react-nestjs/apps/web/src/components/Brand/Brand.module.css +125 -0
  314. package/template-vp-monorepo-react-nestjs/apps/web/src/components/Brand/Brand.tsx +56 -0
  315. package/template-vp-monorepo-react-nestjs/apps/web/src/components/DraftProTable/DraftProTable.tsx +11 -5
  316. package/template-vp-monorepo-react-nestjs/apps/web/src/components/Icon/SvgAsset/IconSelector.tsx +38 -0
  317. package/template-vp-monorepo-react-nestjs/apps/web/src/components/Icon/SvgAsset/SvgAssetIcon.tsx +14 -0
  318. package/template-vp-monorepo-react-nestjs/apps/web/src/components/Icon/SvgAsset/SvgAssetRegistry.ts +32 -0
  319. package/template-vp-monorepo-react-nestjs/apps/web/src/components/Icon/SvgAsset/index.ts +10 -0
  320. package/template-vp-monorepo-react-nestjs/apps/web/src/components/Icon/svg-icon/SvgIcon.tsx +0 -2
  321. package/template-vp-monorepo-react-nestjs/apps/web/src/components/Loading/PageLoading.tsx +5 -1
  322. package/template-vp-monorepo-react-nestjs/apps/web/src/components/LocaleSwitch/LocaleSwitch.tsx +52 -0
  323. package/template-vp-monorepo-react-nestjs/apps/web/src/components/PasswordActions/ChangePasswordDialog.tsx +90 -0
  324. package/template-vp-monorepo-react-nestjs/apps/web/src/components/PasswordActions/PasswordFields.module.css +12 -0
  325. package/template-vp-monorepo-react-nestjs/apps/web/src/components/PasswordActions/PasswordFields.tsx +54 -0
  326. package/template-vp-monorepo-react-nestjs/apps/web/src/components/PasswordActions/ResetAccountPasswordDialog.tsx +100 -0
  327. package/template-vp-monorepo-react-nestjs/apps/web/src/components/PasswordActions/change-password-session.ts +13 -0
  328. package/template-vp-monorepo-react-nestjs/apps/web/src/components/RouteTransition/RouteTransition.css +60 -0
  329. package/template-vp-monorepo-react-nestjs/apps/web/src/components/RouteTransition/RouteTransition.tsx +44 -0
  330. package/template-vp-monorepo-react-nestjs/apps/web/src/components/Selector/BasicTableSelector/BasicTableSelector.tsx +218 -0
  331. package/template-vp-monorepo-react-nestjs/apps/web/src/components/Selector/BasicTableSelector/BasicTableSelectorSelection.ts +91 -0
  332. package/template-vp-monorepo-react-nestjs/apps/web/src/components/Selector/BasicTableSelector/BasicTableSelectorTypes.ts +60 -0
  333. package/template-vp-monorepo-react-nestjs/apps/web/src/components/Selector/BasicTableSelector/README.md +110 -0
  334. package/template-vp-monorepo-react-nestjs/apps/web/src/components/Selector/BasicTableSelector/index.ts +7 -0
  335. package/template-vp-monorepo-react-nestjs/apps/web/src/components/Selector/GlobalAccountSelect/GlobalAccountSelect.tsx +211 -0
  336. package/template-vp-monorepo-react-nestjs/apps/web/src/components/Selector/GlobalAccountSelect/GlobalAccountSelectTypes.ts +75 -0
  337. package/template-vp-monorepo-react-nestjs/apps/web/src/components/Selector/GlobalAccountSelect/README.md +35 -0
  338. package/template-vp-monorepo-react-nestjs/apps/web/src/components/Selector/GlobalAccountSelect/index.ts +9 -0
  339. package/template-vp-monorepo-react-nestjs/apps/web/src/components/Selector/OrganizationMemberSelector/OrganizationMemberBrowser.tsx +146 -0
  340. package/template-vp-monorepo-react-nestjs/apps/web/src/components/Selector/OrganizationMemberSelector/OrganizationMemberCandidateColumns.tsx +137 -0
  341. package/template-vp-monorepo-react-nestjs/apps/web/src/components/Selector/OrganizationMemberSelector/OrganizationMemberFilterPanel.tsx +209 -0
  342. package/template-vp-monorepo-react-nestjs/apps/web/src/components/Selector/OrganizationMemberSelector/OrganizationMemberSelector.tsx +196 -0
  343. package/template-vp-monorepo-react-nestjs/apps/web/src/components/Selector/OrganizationMemberSelector/OrganizationMemberSelectorTypes.ts +103 -0
  344. package/template-vp-monorepo-react-nestjs/apps/web/src/components/Selector/OrganizationMemberSelector/README.md +8 -0
  345. package/template-vp-monorepo-react-nestjs/apps/web/src/components/Selector/OrganizationMemberSelector/index.ts +13 -0
  346. package/template-vp-monorepo-react-nestjs/apps/web/src/components/Selector/README.md +13 -0
  347. package/template-vp-monorepo-react-nestjs/apps/web/src/components/Selector/index.ts +30 -0
  348. package/template-vp-monorepo-react-nestjs/apps/web/src/config/theme.ts +41 -9
  349. package/template-vp-monorepo-react-nestjs/apps/web/src/hooks/useLatestDialogRequest.ts +71 -0
  350. package/template-vp-monorepo-react-nestjs/apps/web/src/i18n/config.ts +40 -0
  351. package/template-vp-monorepo-react-nestjs/apps/web/src/i18n/index.ts +10 -0
  352. package/template-vp-monorepo-react-nestjs/apps/web/src/i18n/instance.ts +36 -0
  353. package/template-vp-monorepo-react-nestjs/apps/web/src/i18n/ui-locale.ts +30 -0
  354. package/template-vp-monorepo-react-nestjs/apps/web/src/layouts/{BasicLayout.tsx → BasicLayout/index.tsx} +42 -35
  355. package/template-vp-monorepo-react-nestjs/apps/web/src/layouts/WorkspaceLayout/components/WorkspaceNavigationBoundary.tsx +50 -0
  356. package/template-vp-monorepo-react-nestjs/apps/web/src/layouts/WorkspaceLayout/index.tsx +196 -0
  357. package/template-vp-monorepo-react-nestjs/apps/web/src/layouts/WorkspaceLayout/workspace-landing.css +119 -0
  358. package/template-vp-monorepo-react-nestjs/apps/web/src/layouts/WorkspaceLayout/workspace-surfaces.css +110 -0
  359. package/template-vp-monorepo-react-nestjs/apps/web/src/layouts/WorkspaceLayout/workspace.css +223 -0
  360. package/template-vp-monorepo-react-nestjs/apps/web/src/locales/en_US.json +639 -1
  361. package/template-vp-monorepo-react-nestjs/apps/web/src/locales/zh_CN.json +621 -1
  362. package/template-vp-monorepo-react-nestjs/apps/web/src/main.tsx +8 -2
  363. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/api.ts +226 -0
  364. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/audit.tsx +169 -0
  365. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/components/AdministratorDialog.tsx +128 -0
  366. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/components/CleanupDialog.tsx +140 -0
  367. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/components/CompanyHierarchyDialog.tsx +244 -0
  368. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/components/EntityFormDialog.tsx +285 -0
  369. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/components/EntitySelectors/index.ts +6 -0
  370. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/components/EntitySelectors/selector-requests.ts +59 -0
  371. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/components/MemberAffiliations/MemberOrganizationsDialog.tsx +188 -0
  372. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/components/MemberAffiliations/MemberPositionsDialog.tsx +116 -0
  373. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/components/MemberAffiliations/affiliation-loaders.ts +18 -0
  374. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/components/MemberAffiliations/index.ts +5 -0
  375. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/components/MemberOnboarding/AddProjectMemberDialog.tsx +75 -0
  376. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/components/MemberOnboarding/CompanyMemberInvitation/CompanyMemberInvitationDialog.tsx +246 -0
  377. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/components/MemberOnboarding/CompanyMemberInvitation/InvitationRecordsTable.tsx +152 -0
  378. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/components/MemberOnboarding/CompanyMemberInvitation/invitation-link.ts +9 -0
  379. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/components/MemberOnboarding/MemberOnboardingActions.tsx +79 -0
  380. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/components/MemberOnboarding/RegisterCompanyMember/RegisterCompanyMemberDialog.module.css +12 -0
  381. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/components/MemberOnboarding/RegisterCompanyMember/RegisterCompanyMemberDialog.tsx +122 -0
  382. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/components/MemberRolesDialog.tsx +80 -0
  383. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/components/MemberTable/MemberTableColumns.tsx +234 -0
  384. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/components/MemberTable/index.ts +2 -0
  385. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/components/MemberTable/member-candidate-cache.ts +12 -0
  386. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/components/MenuFormDialog.tsx +251 -0
  387. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/components/RoleFormDialog.tsx +73 -0
  388. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/components/RolePermissionsDialog.tsx +185 -0
  389. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/entities.tsx +268 -0
  390. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/home.tsx +67 -0
  391. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/members.tsx +310 -0
  392. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/menus/api.ts +74 -0
  393. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/menus/index.tsx +325 -0
  394. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/profile.tsx +160 -0
  395. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/roles.tsx +173 -0
  396. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/use-access.ts +35 -0
  397. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/error/404.tsx +20 -0
  398. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/error/error.tsx +42 -0
  399. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/examples/i18n/index.tsx +20 -38
  400. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/examples/pro-table/components/ProjectFormDialog.tsx +46 -41
  401. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/examples/pro-table/config/columns.tsx +20 -15
  402. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/examples/pro-table/config/index.ts +32 -22
  403. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/examples/pro-table/draft/components/DraftProjectFormDialog.tsx +41 -34
  404. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/examples/pro-table/draft/config/columns.tsx +27 -20
  405. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/examples/pro-table/draft/config/projects.ts +21 -13
  406. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/examples/pro-table/draft/index.tsx +47 -27
  407. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/examples/pro-table/index.tsx +51 -36
  408. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/home/index.tsx +9 -6
  409. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/login/api.ts +3 -0
  410. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/login/index.tsx +62 -82
  411. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/login/login-form.css +199 -0
  412. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/login/login.css +146 -124
  413. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/member-invitations/accept.css +47 -0
  414. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/member-invitations/accept.tsx +143 -0
  415. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/member-invitations/api.ts +20 -0
  416. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/organization/api.ts +91 -0
  417. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/organization/components/MoveOrganizationUnitDialog.tsx +82 -0
  418. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/organization/components/OrganizationBrowser/OrganizationMemberColumns.tsx +87 -0
  419. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/organization/components/OrganizationBrowser/OrganizationMemberHeader.tsx +102 -0
  420. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/organization/components/OrganizationBrowser/OrganizationTreeModel.tsx +59 -0
  421. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/organization/components/OrganizationBrowser/OrganizationTreePanel.tsx +88 -0
  422. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/organization/components/OrganizationBrowser/index.ts +11 -0
  423. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/organization/components/OrganizationBrowser/organization-loaders.ts +47 -0
  424. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/organization/components/OrganizationBrowser/organization-member-filter-loaders.ts +187 -0
  425. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/organization/components/OrganizationMembersDialog.tsx +207 -0
  426. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/organization/components/OrganizationUnitDialog.tsx +110 -0
  427. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/organization/index.tsx +258 -0
  428. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/organization-templates/api.ts +53 -0
  429. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/organization-templates/components/OrganizationTemplateDialog/TemplateDefinitionTabs.tsx +189 -0
  430. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/organization-templates/components/OrganizationTemplateDialog/index.tsx +135 -0
  431. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/organization-templates/components/OrganizationTemplateDialog/types.ts +25 -0
  432. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/organization-templates/index.tsx +201 -0
  433. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/positions/api.ts +81 -0
  434. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/positions/components/PositionFormDialog.tsx +86 -0
  435. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/positions/components/PositionMembersDialog.tsx +102 -0
  436. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/positions/index.tsx +198 -0
  437. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/positions/loaders.ts +35 -0
  438. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/register/api.ts +14 -0
  439. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/register/index.tsx +157 -0
  440. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/workspaces/api.ts +32 -0
  441. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/workspaces/index.tsx +146 -0
  442. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/workspaces/state.ts +24 -0
  443. package/template-vp-monorepo-react-nestjs/apps/web/src/router/AGENTS.MD +6 -0
  444. package/template-vp-monorepo-react-nestjs/apps/web/src/router/index.tsx +2 -46
  445. package/template-vp-monorepo-react-nestjs/apps/web/src/router/lazy-load/index.tsx +26 -0
  446. package/template-vp-monorepo-react-nestjs/apps/web/src/router/middleware/README.md +23 -0
  447. package/template-vp-monorepo-react-nestjs/apps/web/src/router/middleware/auth.ts +6 -0
  448. package/template-vp-monorepo-react-nestjs/apps/web/src/router/middleware/index.ts +4 -0
  449. package/template-vp-monorepo-react-nestjs/apps/web/src/router/middleware/workspace/access.ts +23 -0
  450. package/template-vp-monorepo-react-nestjs/apps/web/src/router/middleware/workspace/data.ts +55 -0
  451. package/template-vp-monorepo-react-nestjs/apps/web/src/router/middleware/workspace/entry.ts +52 -0
  452. package/template-vp-monorepo-react-nestjs/apps/web/src/router/modules/access/page.tsx +20 -0
  453. package/template-vp-monorepo-react-nestjs/apps/web/src/router/modules/auth.tsx +17 -0
  454. package/template-vp-monorepo-react-nestjs/apps/web/src/router/modules/company.tsx +30 -0
  455. package/template-vp-monorepo-react-nestjs/apps/web/src/router/modules/entry.tsx +20 -0
  456. package/template-vp-monorepo-react-nestjs/apps/web/src/router/modules/examples.tsx +23 -0
  457. package/template-vp-monorepo-react-nestjs/apps/web/src/router/modules/fallback.tsx +13 -0
  458. package/template-vp-monorepo-react-nestjs/apps/web/src/router/modules/index.tsx +32 -0
  459. package/template-vp-monorepo-react-nestjs/apps/web/src/router/modules/platform.tsx +27 -0
  460. package/template-vp-monorepo-react-nestjs/apps/web/src/router/modules/project.tsx +28 -0
  461. package/template-vp-monorepo-react-nestjs/apps/web/src/router/page-registry.tsx +94 -0
  462. package/template-vp-monorepo-react-nestjs/apps/web/src/styles/dream.css +34 -0
  463. package/template-vp-monorepo-react-nestjs/apps/web/src/styles/index.css +6 -0
  464. package/template-vp-monorepo-react-nestjs/apps/web/src/types/auto-imports.d.ts +26 -0
  465. package/template-vp-monorepo-react-nestjs/apps/web/src/utils/organization-assignment.ts +66 -0
  466. package/template-vp-monorepo-react-nestjs/apps/web/src/utils/request/core/index.ts +48 -13
  467. package/template-vp-monorepo-react-nestjs/apps/web/src/utils/request/core/utils.ts +5 -0
  468. package/template-vp-monorepo-react-nestjs/apps/web/src/utils/request/index.ts +7 -2
  469. package/template-vp-monorepo-react-nestjs/apps/web/src/utils/request/workspace.ts +82 -0
  470. package/template-vp-monorepo-react-nestjs/apps/web/src/utils/safe-next.ts +36 -0
  471. package/template-vp-monorepo-react-nestjs/apps/web/src/utils/storage/cookie.ts +1 -0
  472. package/template-vp-monorepo-react-nestjs/apps/web/src/utils/storage/session.ts +1 -0
  473. package/template-vp-monorepo-react-nestjs/apps/web/test/i18n-locale.spec.ts +22 -0
  474. package/template-vp-monorepo-react-nestjs/apps/web/test/icon-selector.spec.tsx +23 -0
  475. package/template-vp-monorepo-react-nestjs/apps/web/test/latest-dialog-request.spec.ts +89 -0
  476. package/template-vp-monorepo-react-nestjs/apps/web/test/member-invitation-navigation.spec.ts +34 -0
  477. package/template-vp-monorepo-react-nestjs/apps/web/test/organization-assignment.spec.ts +137 -0
  478. package/template-vp-monorepo-react-nestjs/apps/web/test/password/password-actions.spec.ts +40 -0
  479. package/template-vp-monorepo-react-nestjs/apps/web/test/password/password-reset-action.spec.ts +66 -0
  480. package/template-vp-monorepo-react-nestjs/apps/web/test/password/workspaces-password-entry.spec.tsx +71 -0
  481. package/template-vp-monorepo-react-nestjs/apps/web/test/request.spec.ts +1 -0
  482. package/template-vp-monorepo-react-nestjs/apps/web/test/router/access.spec.ts +136 -0
  483. package/template-vp-monorepo-react-nestjs/apps/web/test/router/config.ts +140 -0
  484. package/template-vp-monorepo-react-nestjs/apps/web/test/router/entry.spec.ts +179 -0
  485. package/template-vp-monorepo-react-nestjs/apps/web/test/router/workspace-data.spec.ts +112 -0
  486. package/template-vp-monorepo-react-nestjs/apps/web/test/selector/global-account-select.spec.ts +311 -0
  487. package/template-vp-monorepo-react-nestjs/apps/web/test/selector/organization-member-selector.spec.ts +454 -0
  488. package/template-vp-monorepo-react-nestjs/apps/web/test/selector/selector-selection.spec.ts +132 -0
  489. package/template-vp-monorepo-react-nestjs/apps/web/test/storage.spec.ts +1 -0
  490. package/template-vp-monorepo-react-nestjs/apps/web/test/tsconfig.json +2 -2
  491. package/template-vp-monorepo-react-nestjs/apps/web/test/workspace-navigation-boundary.spec.tsx +169 -0
  492. package/template-vp-monorepo-react-nestjs/apps/web/test/workspace-navigation.spec.ts +105 -0
  493. package/template-vp-monorepo-react-nestjs/apps/web/test/workspace-requests.spec.ts +174 -0
  494. package/template-vp-monorepo-react-nestjs/apps/web/vite.config.ts +84 -35
  495. package/template-vp-monorepo-react-nestjs/apps/web-vue/package.json +2 -0
  496. package/template-vp-monorepo-react-nestjs/apps/web-vue/src/api/index.ts +1 -0
  497. package/template-vp-monorepo-react-nestjs/apps/web-vue/src/hooks/chart/useEcharts.ts +13 -1
  498. package/template-vp-monorepo-react-nestjs/apps/web-vue/src/layout/default/header/index.vue +1 -0
  499. package/template-vp-monorepo-react-nestjs/apps/web-vue/src/layout/default/index.vue +6 -2
  500. package/template-vp-monorepo-react-nestjs/apps/web-vue/src/router/guard/index.ts +1 -0
  501. package/template-vp-monorepo-react-nestjs/apps/web-vue/src/router/guard/permissionGuard.ts +1 -0
  502. package/template-vp-monorepo-react-nestjs/apps/web-vue/src/router/index.ts +1 -0
  503. package/template-vp-monorepo-react-nestjs/apps/web-vue/src/store/index.ts +1 -0
  504. package/template-vp-monorepo-react-nestjs/apps/web-vue/src/store/modules/user.ts +1 -0
  505. package/template-vp-monorepo-react-nestjs/apps/web-vue/src/types/auto-import.d.ts +2 -0
  506. package/template-vp-monorepo-react-nestjs/apps/web-vue/src/utils/request/core/index.ts +30 -0
  507. package/template-vp-monorepo-react-nestjs/apps/web-vue/src/utils/request/core/utils.ts +5 -0
  508. package/template-vp-monorepo-react-nestjs/apps/web-vue/src/utils/request/index.ts +2 -0
  509. package/template-vp-monorepo-react-nestjs/apps/web-vue/src/views/example/echart/config.ts +1 -0
  510. package/template-vp-monorepo-react-nestjs/apps/web-vue/tsconfig.tsbuildinfo +1 -1
  511. package/template-vp-monorepo-react-nestjs/package.json +1 -8
  512. package/template-vp-monorepo-react-nestjs/packages/i18n/cli/README.md +2 -0
  513. package/template-vp-monorepo-react-nestjs/packages/i18n/cli/src/command.ts +22 -2
  514. package/template-vp-monorepo-react-nestjs/packages/i18n/cli/src/config.ts +1 -0
  515. package/template-vp-monorepo-react-nestjs/packages/i18n/cli/src/files.ts +1 -0
  516. package/template-vp-monorepo-react-nestjs/packages/i18n/cli/src/load-config.ts +8 -0
  517. package/template-vp-monorepo-react-nestjs/packages/i18n/cli/src/report.ts +2 -0
  518. package/template-vp-monorepo-react-nestjs/packages/i18n/cli/src/scanner.test.ts +88 -0
  519. package/template-vp-monorepo-react-nestjs/packages/i18n/cli/src/scanner.ts +42 -8
  520. package/template-vp-monorepo-react-nestjs/packages/i18n/cli/src/sync.ts +12 -0
  521. package/template-vp-monorepo-react-nestjs/packages/i18n/cli/test/command.test.ts +37 -0
  522. package/template-vp-monorepo-react-nestjs/packages/i18n/cli/test/temporary-directory.ts +5 -0
  523. package/template-vp-monorepo-react-nestjs/packages/i18n/core/src/format.ts +1 -0
  524. package/template-vp-monorepo-react-nestjs/packages/i18n/core/src/i18n.ts +14 -0
  525. package/template-vp-monorepo-react-nestjs/packages/i18n/core/src/storage.ts +8 -0
  526. package/template-vp-monorepo-react-nestjs/packages/i18n/core/src/store.ts +9 -0
  527. package/template-vp-monorepo-react-nestjs/packages/i18n/react/src/index.tsx +5 -0
  528. package/template-vp-monorepo-react-nestjs/packages/i18n/react/src/use-store.ts +18 -5
  529. package/template-vp-monorepo-react-nestjs/packages/i18n/vue/src/index.ts +6 -0
  530. package/template-vp-monorepo-react-nestjs/packages/i18n/vue/src/use-store.ts +3 -0
  531. package/template-vp-monorepo-react-nestjs/packages/shared/package.json +5 -1
  532. package/template-vp-monorepo-react-nestjs/packages/shared/src/index.ts +2 -13
  533. package/template-vp-monorepo-react-nestjs/packages/shared/src/types/access-maintenance.ts +68 -0
  534. package/template-vp-monorepo-react-nestjs/packages/shared/src/types/access-menus.ts +94 -0
  535. package/template-vp-monorepo-react-nestjs/packages/shared/src/types/access-resources.ts +168 -0
  536. package/template-vp-monorepo-react-nestjs/packages/shared/src/types/access.ts +71 -0
  537. package/template-vp-monorepo-react-nestjs/packages/shared/src/types/auth.ts +23 -0
  538. package/template-vp-monorepo-react-nestjs/packages/shared/src/types/index.ts +9 -0
  539. package/template-vp-monorepo-react-nestjs/packages/shared/src/types/organization/models.ts +361 -0
  540. package/template-vp-monorepo-react-nestjs/packages/shared/src/utils/access-catalog.ts +304 -0
  541. package/template-vp-monorepo-react-nestjs/packages/shared/src/utils/access-scope.ts +97 -0
  542. package/template-vp-monorepo-react-nestjs/packages/shared/src/utils/account.ts +1 -0
  543. package/template-vp-monorepo-react-nestjs/packages/shared/src/utils/index.ts +65 -0
  544. package/template-vp-monorepo-react-nestjs/packages/shared/src/utils/organization/contracts.ts +237 -0
  545. package/template-vp-monorepo-react-nestjs/packages/shared/src/utils/record.ts +10 -0
  546. package/template-vp-monorepo-react-nestjs/packages/shared/src/utils/session-terminal.ts +1 -0
  547. package/template-vp-monorepo-react-nestjs/packages/shared/test/access.spec.ts +194 -0
  548. package/template-vp-monorepo-react-nestjs/packages/shared/test/organization.spec.ts +168 -0
  549. package/template-vp-monorepo-react-nestjs/pnpm-workspace.yaml +103 -69
  550. package/template-vp-monorepo-react-nestjs/scripts/enterprise-qa/browser.mjs +696 -0
  551. package/template-vp-monorepo-react-nestjs/scripts/enterprise-qa/http-support.mjs +105 -0
  552. package/template-vp-monorepo-react-nestjs/scripts/enterprise-qa/http.mjs +1091 -0
  553. package/template-vp-monorepo-react-nestjs/scripts/enterprise-qa/legacy-http.mjs +140 -0
  554. package/template-vp-monorepo-react-nestjs/scripts/enterprise-qa/legacy.mjs +196 -0
  555. package/template-vp-monorepo-react-nestjs/scripts/enterprise-qa/runtime.mjs +110 -0
  556. package/template-vp-monorepo-react-nestjs/scripts/with-enterprise-test-env.mjs +80 -0
  557. package/template-vp-monorepo-react-nestjs/src/types/auto-imports.d.ts +60 -0
  558. package/template-vp-monorepo-react-nestjs/tsconfig.lib.json +1 -1
  559. package/template-vp-react/package.json +12 -12
  560. package/template-vp-react/src/types/auto-imports.d.ts +2 -0
  561. package/template-vp-vue-eslint-vapor/.vscode/settings.json +53 -0
  562. package/template-vp-vue-eslint-vapor/package.json +21 -20
  563. package/template-vp-vue-eslint-vapor/pnpm-workspace.yaml +0 -24
  564. package/template-vp-vue-eslint-vapor/src/main.ts +2 -3
  565. package/template-vp-vue-eslint-vapor/vite.config.ts +26 -31
  566. package/template-vp-monorepo-react-nestjs/.spaces/01./344/274/201/344/270/232/347/272/247/351/241/271/347/233/256/347/272/247//351/234/200/346/261/202/346/226/207/346/241/243.md +0 -177
  567. package/template-vp-monorepo-react-nestjs/apps/web/src/layouts/BasicLayout.module.css +0 -17
  568. package/template-vp-monorepo-react-nestjs/apps/web/src/router/modules/.gitkeep +0 -0
  569. package/template-vp-react/.agents/rules/SVG/344/275/277/347/224/250.md +0 -8
  570. package/template-vp-react/.vscode/settings.json +0 -11
  571. package/template-vp-react/AGENTS.md +0 -11
  572. /package/{template-vp-vue-eslint-vapor → template-pnpm-vp-monorepo}/.vscode/extensions.json +0 -0
  573. /package/template-vp-monorepo-react-nestjs/apps/web/src/assets/{hero.png → image/hero.png} +0 -0
  574. /package/template-vp-monorepo-react-nestjs/apps/web/src/assets/{react.svg → svg/react.svg} +0 -0
  575. /package/template-vp-monorepo-react-nestjs/apps/web/src/assets/{vite.svg → svg/vite.svg} +0 -0
@@ -0,0 +1,580 @@
1
+ # 企业、项目与菜单权限实施契约
2
+
3
+ 状态:当前实现契约,2026-09-18 已统一管理员选择、企业成员直接注册及项目成员候选边界。企业邀请只确认产品入口,具体协议待确认,不属于本契约的现行实现范围。需求来源为[需求文档](./需求文档.md);前后端共同遵循本文,发现缺失经统一更新后同步,不能各自发明字段或端点。
4
+
5
+ ## 1. 现有工程约定
6
+
7
+ - 本期实现 `apps/web`(React)与 `apps/server`(NestJS),不改 `apps/web-vue`;保留既有上传的 `ownerId` 权限和 Cookie / Storage 职责。
8
+ - 共享包已有源码目录为 `packages/shared/src/types`、`packages/shared/src/utils`,已有发布入口为 `shared/types`、`shared/utils`。需求中的共享目录按此现有结构落地,不另建重复目录。公共请求、返回、分页、权限目录字段均从共享包导出;服务端 Zod DTO 校验这些类型,不向前端泄漏 Drizzle 实体。
9
+ - 以下路径不含环境中的 API 代理前缀。成功直接返回下述 JSON,不增加 `{code,data}` 包装;失败沿用 `ApiFailure = { code: string; message: string; details?: {path?: string; code: string; message: string}[] }`。请求追踪使用 `x-request-id`,审计使用同一个服务端 `request.id`。
10
+ - 查询成功 200;创建企业、项目、成员、自定义角色、菜单节点成功 201;其他写操作成功 200。删除返回 `{deleted: true}`,不返回 204。已经不存在的普通删除目标返回 404;清理维护操作另有幂等约定。
11
+ - 所有新管理端点声明访问策略,默认拒绝未声明策略的端点。现有公开根页、注册、登录、幂等退出保留 `@Public()`;`/auth/me` 明确为已登录策略;上传明确为已登录且 owner 策略。测试 DB / Redis 模块移出默认 AppModule,不能以“兼容旧接口”为由继续暴露。
12
+ - 继续使用现有 alova 实例、页面旁 `api.ts`、React Router middleware、现有弹窗 `show/hide` 规范,不恢复已删除的 auth Provider / Guard 目录。Web 文件遵守其 AGENTS 与按需规则。
13
+
14
+ ## 2. 基础类型与字段
15
+
16
+ ```ts
17
+ type ScopeType = 'platform' | 'company' | 'project'
18
+ type AccessScope =
19
+ | { type: 'platform' }
20
+ | { type: 'company'; companyId: string }
21
+ | { type: 'project'; companyId: string; projectId: string }
22
+ type EntityStatus = 'active' | 'disabled'
23
+ type AccountStatus = 'active' | 'locked' | 'disabled' // 沿用 users.status
24
+ type BuiltinRole = 'administrator' | 'member' | null
25
+ interface PageQuery {
26
+ page?: number
27
+ pageSize?: number
28
+ query?: string
29
+ }
30
+ interface PageResult<T> {
31
+ items: T[]
32
+ total: number
33
+ page: number
34
+ pageSize: number
35
+ }
36
+ interface VersionRequest {
37
+ expectedVersion: number
38
+ }
39
+ interface StatusRequest extends VersionRequest {
40
+ status: EntityStatus
41
+ }
42
+ interface DeleteResult {
43
+ deleted: true
44
+ }
45
+ interface UserSummary {
46
+ id: string
47
+ account: string
48
+ name: string
49
+ }
50
+ interface AccountRecord extends UserSummary {
51
+ status: AccountStatus
52
+ createdAt: string
53
+ updatedAt: string
54
+ platformRoleIds: string[]
55
+ }
56
+ interface CompanyRecord {
57
+ id: string
58
+ name: string
59
+ code: string
60
+ description: string
61
+ status: EntityStatus
62
+ version: number
63
+ createdAt: string
64
+ updatedAt: string
65
+ }
66
+ interface ProjectRecord extends CompanyRecord {
67
+ companyId: string
68
+ }
69
+ interface AdministratorSummary extends UserSummary {
70
+ accountStatus: AccountStatus
71
+ memberStatus: EntityStatus
72
+ effective: boolean
73
+ }
74
+ interface CompanyDetail extends CompanyRecord {
75
+ administrators: AdministratorSummary[]
76
+ }
77
+ interface ProjectDetail extends ProjectRecord {
78
+ administrators: AdministratorSummary[]
79
+ }
80
+ interface MemberRecord {
81
+ id: string
82
+ userId: string
83
+ account: string
84
+ name: string
85
+ status: EntityStatus
86
+ accountStatus: AccountStatus
87
+ roleIds: string[]
88
+ roleNames: string[]
89
+ version: number
90
+ createdAt: string
91
+ updatedAt: string
92
+ }
93
+ interface RoleRecord {
94
+ id: string
95
+ scope: AccessScope
96
+ name: string
97
+ description: string
98
+ builtin: BuiltinRole
99
+ permissionKeys: string[]
100
+ version: number
101
+ memberCount: number
102
+ assignable: boolean
103
+ createdAt: string
104
+ updatedAt: string
105
+ }
106
+ ```
107
+
108
+ - 所有实体 ID 使用 UUID 字符串;`permissionKey`、`routeKey` 使用代码目录中的稳定字符串。日期均输出 ISO 8601 UTC 字符串。
109
+ - `page` 默认 1,正整数;`pageSize` 默认 20,范围 1–100;超界返回 400,不静默改变用户值。`query` trim 后最多 100 字,空串等同不筛选。列表按 `createdAt DESC, id DESC` 稳定排序;菜单按 `sort ASC, id ASC`。搜索匹配名称/编码或名称/账号,不将 `%`、`_` 当用户输入的通配符。
110
+ - 企业/项目 `name` trim 后 2–100 字;`code` trim 后 2–32 字,`^[A-Za-z0-9_-]+$`,规范化为小写。企业编码全平台唯一,项目编码在企业内唯一。`description` trim 后 0–500 字,省略创建时写空串;PATCH 省略字段表示不改。
111
+ - 角色名称 2–100 字,同一作用域唯一;描述 0–500 字。内置角色名称由系统维护。首期自定义角色不另增启停状态,通过修改权限、撤销分配或删除未被使用的角色管理。
112
+ - `status` 表示对象自身状态,不因父级停用而批量改写。新建企业、项目、成员、自定义角色默认可用。版本从 1 起,相关修改后递增;过期提交 409。账号状态操作沿用 users 表,没有请求版本字段。
113
+ - 所有请求 DTO 拒绝未知字段。数组不允许重复项;角色/权限数组最多 500 项。所有返回均显式选择字段,不返回密码散列、token 或数据库内部对象。
114
+ - 账号沿用 `normalizeAccount()`,完整账号 4–32 位字母、数字、下划线;注册 `name` 2–100,密码 8–128。注册不自动登录,也不加入任何工作空间。
115
+
116
+ ## 3. 工作空间与上下文
117
+
118
+ ```ts
119
+ interface WorkspaceEntry {
120
+ scope: AccessScope
121
+ name: string
122
+ companyName?: string
123
+ administrator: ScopeType | null
124
+ }
125
+ interface WorkspacesResult {
126
+ user: UserSummary
127
+ workspaces: WorkspaceEntry[]
128
+ }
129
+ type MenuNodeType = 'directory' | 'page' | 'operation'
130
+ interface MenuNode {
131
+ id: string
132
+ scopeType: ScopeType
133
+ parentId: string | null
134
+ type: MenuNodeType
135
+ name: string
136
+ icon: string
137
+ sort: number
138
+ hidden: boolean
139
+ status: EntityStatus
140
+ routeKey: string | null
141
+ permissionKey: string | null
142
+ protected: boolean
143
+ children: MenuNode[]
144
+ }
145
+ interface AccessContext {
146
+ user: UserSummary
147
+ scope: AccessScope
148
+ administrator: ScopeType | null
149
+ permissionKeys: string[]
150
+ menus: MenuNode[]
151
+ menuVersion: number
152
+ catalogVersion: string
153
+ }
154
+ interface MenuTreeResult {
155
+ scopeType: ScopeType
156
+ version: number
157
+ items: MenuNode[]
158
+ }
159
+ interface PermissionDefinition {
160
+ key: string
161
+ scopeType: ScopeType
162
+ kind: 'page' | 'operation'
163
+ title: string
164
+ routeKey: string
165
+ pagePermissionKey: string | null
166
+ adminOnly: boolean
167
+ deprecated: boolean
168
+ }
169
+ interface PermissionTreeResult {
170
+ catalogVersion: string
171
+ items: MenuNode[]
172
+ permissions: PermissionDefinition[]
173
+ grantablePermissionKeys: string[]
174
+ }
175
+ ```
176
+
177
+ | 方法与路径 | 返回 | 访问策略 |
178
+ | ------------------------------------------------------ | ------------------ | ----------------------------------------------------- |
179
+ | GET `/workspaces` | `WorkspacesResult` | 有效登录用户;只列可进入的 active 范围 |
180
+ | GET `/platform/access` | `AccessContext` | 有至少一个平台角色的有效用户 |
181
+ | GET `/companies/:companyId/access` | `AccessContext` | 企业 active、账号及企业成员有效 |
182
+ | GET `/companies/:companyId/projects/:projectId/access` | `AccessContext` | 所属企业及项目 active,且有效项目成员或所属企业管理员 |
183
+
184
+ 企业管理员不需要 `project_members` 记录即可列出并进入本企业所有 active 项目;在项目上下文中 `administrator: 'company'`。显式项目成员停用不屏蔽企业管理员能力。`/workspaces` 不接受任意用户 ID;无企业的新账号返回空列表,前端显示等待添加;拥有平台角色则仍显示平台空间。
185
+
186
+ `AccessContext.permissionKeys` 是同作用域角色并集再扣除未注册、已下线及菜单自身/祖先停用的权限。按钮还须满足所属页面访问权限。内置管理员自动获得当前作用域的全部已注册功能权限,但仍受功能状态约束;项目上下文中的企业管理员按项目内置管理员权限计算。目录只用于导航。
187
+
188
+ `menus` 只返回授权且可见的导航树;隐藏页及其导航子项不出现,但其有效权限仍出现在 `permissionKeys`,支持直达页面。按钮节点可包含在树中供消费,但布局不渲染为导航。`/access` 允许返回空树,不能因为用户没有某个页面权限就拒绝获取自己的上下文。
189
+
190
+ 同范围无权限或已停用返回 403;不存在/非成员企业、项目关系不匹配、非企业管理员且不是该项目成员,统一返回 404。无效账号与失效登录返回 401。资源 ID 的内部查询必须同时约束作用域;不能先加载其他租户完整资源再只做前端过滤。
191
+
192
+ ## 4. 页面、权限和 routeKey 目录
193
+
194
+ 页面权限固定为 `${routeKey}.read`。下表操作列为完整权限的最后一段,例如 `company.members.add`;每个操作绑定本行页面,必须同时拥有页面 `.read`。标记 `*` 的操作额外要求内置管理员身份,不能进入自定义角色授权集合。所有未标记操作可被自定义角色授予,但不能超过操作者有权授予的权限。
195
+
196
+ | scope | routeKey | 前端路径 | 页面名称 | 操作后缀 |
197
+ | -------- | -------------------- | --------------------------------------------------- | ------------ | ------------------------------------------- |
198
+ | platform | `platform.home` | `/platform` | 平台工作台 | — |
199
+ | platform | `platform.companies` | `/platform/companies` | 企业管理 | `create*`, `status`, `administrator*` |
200
+ | platform | `platform.accounts` | `/platform/accounts` | 全局账号 | `status`, `roles`, `reset-password*` |
201
+ | platform | `platform.roles` | `/platform/roles` | 平台角色 | `create`, `update`, `delete`, `permissions` |
202
+ | platform | `platform.menus` | `/platform/menus` | 菜单管理 | `create`, `update`, `delete`, `cleanup*` |
203
+ | platform | `platform.audit` | `/platform/audit` | 平台操作日志 | — |
204
+ | company | `company.home` | `/companies/:companyId` | 企业工作台 | — |
205
+ | company | `company.profile` | `/companies/:companyId/profile` | 企业资料 | `update` |
206
+ | company | `company.members` | `/companies/:companyId/members` | 企业成员 | `add`, `status`, `remove`, `roles` |
207
+ | company | `company.roles` | `/companies/:companyId/roles` | 企业角色 | `create`, `update`, `delete`, `permissions` |
208
+ | company | `company.projects` | `/companies/:companyId/projects` | 项目管理 | `create*`, `status`, `administrator*` |
209
+ | company | `company.audit` | `/companies/:companyId/audit` | 企业操作日志 | — |
210
+ | project | `project.home` | `/companies/:companyId/projects/:projectId` | 项目工作台 | — |
211
+ | project | `project.profile` | `/companies/:companyId/projects/:projectId/profile` | 项目资料 | `update` |
212
+ | project | `project.members` | `/companies/:companyId/projects/:projectId/members` | 项目成员 | `add`, `status`, `remove`, `roles` |
213
+ | project | `project.roles` | `/companies/:companyId/projects/:projectId/roles` | 项目角色 | `create`, `update`, `delete`, `permissions` |
214
+ | project | `project.audit` | `/companies/:companyId/projects/:projectId/audit` | 项目操作日志 | — |
215
+
216
+ `platform.companies.create` 涉及指定首位企业管理员,故仅平台管理员可用。`company.projects.create/administrator` 仅所属企业内置管理员可用。`platform.menus.cleanup` 仅内置平台管理员可用。企业内和项目内授予/撤销管理员角色时,在成员角色操作权限之外再验证对应管理员委派身份。
217
+
218
+ 普通成员内置角色:平台仅 `platform.home.read`;企业为 `company.home.read` 与 `company.projects.read`(仅列本人加入项目);项目仅 `project.home.read`。新成员默认分配所在范围内置 member 角色,授予首位管理员同时分配 administrator 角色。普通 member 角色及管理员角色定义均不可人工编辑、停用、删除;可以在合法委派和最后管理员规则下修改用户的角色分配。自定义角色空权限合法。
219
+
220
+ 初始三棵菜单树以页面为根节点,operation 为页面子节点;平台可后续插入 directory。首期不需要虚构未实现的目录、按钮或页面。`icon` 保存 `apps/web/src/assets/svg/` 下相对文件名去掉 `.svg` 后的稳定 key,允许使用 `/` 表示子目录,例如 `navigation/dashboard`;空串或当前前端无法解析的 key 使用 `menu-item` 缺省图标。服务端只接受由小写字母、数字和连字符组成的路径段,拒绝路径穿越、SVG/HTML 内容和远程 URL。可选图标由 Web 在构建时自动发现,不由服务端维护第二份文件白名单。
221
+
222
+ ## 5. 企业、账号、项目端点
223
+
224
+ ```ts
225
+ interface CreateCompanyRequest {
226
+ name: string
227
+ code: string
228
+ description?: string
229
+ administratorUserId: string
230
+ }
231
+ interface CreateProjectRequest {
232
+ name: string
233
+ code: string
234
+ description?: string
235
+ administratorUserId: string
236
+ organizationInitialization: ProjectOrganizationInitialization
237
+ }
238
+ interface UpdateProfileRequest extends VersionRequest {
239
+ name?: string
240
+ code?: string
241
+ description?: string
242
+ }
243
+ interface SetAdministratorRequest {
244
+ administratorUserId: string
245
+ replaceUserId?: string
246
+ }
247
+ interface SetAdministratorResult {
248
+ administrator: AdministratorSummary
249
+ replacedUserId: string | null
250
+ }
251
+ interface AccountStatusRequest {
252
+ status: 'active' | 'disabled'
253
+ }
254
+ interface AssignPlatformRolesRequest {
255
+ roleIds: string[]
256
+ }
257
+ ```
258
+
259
+ 企业和项目搜索支持 `PageQuery & {status?: EntityStatus}`。账号搜索支持 `PageQuery & {status?: AccountStatus}`。资料 PATCH 至少提供一个待修改字段。
260
+
261
+ | 方法与路径 | 请求 / 返回 | 权限与边界 |
262
+ | -------------------------------------------------------------- | ----------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------- |
263
+ | GET `/platform/companies` | 查询 → `PageResult<CompanyRecord>` | `platform.companies.read`,含停用企业 |
264
+ | GET `/platform/companies/:companyId` | → `CompanyDetail` | `platform.companies.read`,只提供平台管理资料 |
265
+ | POST `/platform/companies` | `CreateCompanyRequest` → `CompanyDetail` | `platform.companies.create` + 平台管理员 |
266
+ | PATCH `/platform/companies/:companyId/status` | `StatusRequest` → `CompanyRecord` | `platform.companies.status`;恢复检查有效管理员 |
267
+ | POST `/platform/companies/:companyId/administrator` | `SetAdministratorRequest` → `SetAdministratorResult` | `platform.companies.administrator` + 平台管理员;目标企业停用仍可执行 |
268
+ | GET `/platform/accounts` | 查询 → `PageResult<AccountRecord>` | `platform.accounts.read` |
269
+ | PATCH `/platform/accounts/:userId/status` | `AccountStatusRequest` → `AccountRecord` | `platform.accounts.status`;禁用最后企业管理员必须是平台内置管理员,最后平台管理员不可禁用 |
270
+ | PUT `/platform/accounts/:userId/roles` | `AssignPlatformRolesRequest` → `AccountRecord` | `platform.accounts.roles`;全量替换该用户平台角色,不触碰企业/项目角色 |
271
+ | POST `/platform/accounts/:userId/reset-password` | `ResetAccountPasswordRequest` → `ResetAccountPasswordResult` | `platform.accounts.reset-password` + 平台内置管理员;只能重置他人,成功撤销目标全部终端会话;详见[修改密码技术契约](../../06.认证与会话/修改密码/技术契约.md) |
272
+ | GET `/companies/:companyId` | → `CompanyDetail` | `company.profile.read` |
273
+ | PATCH `/companies/:companyId` | `UpdateProfileRequest` → `CompanyRecord` | `company.profile.update` |
274
+ | GET `/companies/:companyId/projects` | 查询 → `PageResult<ProjectRecord>` | `company.projects.read`;企业管理员所有项目,其他成员仅本人显式加入的项目,允许看到这些项目的停用状态 |
275
+ | POST `/companies/:companyId/projects` | `CreateProjectRequest` → `ProjectDetail` | `company.projects.create` + 本企业内置管理员 |
276
+ | PATCH `/companies/:companyId/projects/:projectId/status` | `StatusRequest` → `ProjectRecord` | **按企业作用域** `company.projects.status`;普通企业成员只可操作本人已加入项目;项目本身停用不阻断此上级恢复接口 |
277
+ | GET `/companies/:companyId/projects/:projectId/administrators` | → `ProjectAdministratorsResult`(`AdministratorSummary[]`) | **按企业作用域** `company.projects.administrator` + 企业内置管理员;目标项目停用仍可读取 |
278
+ | POST `/companies/:companyId/projects/:projectId/administrator` | `SetAdministratorRequest` → `SetAdministratorResult` | **按企业作用域** `company.projects.administrator` + 企业管理员;允许对停用项目补任 |
279
+ | GET `/companies/:companyId/projects/:projectId` | → `ProjectDetail` | `project.profile.read` |
280
+ | PATCH `/companies/:companyId/projects/:projectId` | `UpdateProfileRequest` → `ProjectRecord` | `project.profile.update` |
281
+
282
+ 企业创建事务:按 `administratorUserId` 校验有效管理员账号 → 建企业和该范围内置角色 → 建立企业成员及 member / administrator 分配 → 审计 → 提交。项目创建同理,指定用户必须已经是有效企业成员;企业管理员创建者不强制生成项目成员记录。管理员选择器与组织初始化的详细约束见[组织架构技术契约](../组织架构/技术契约.md)。
283
+
284
+ 上级项目管理员列表仅列具有该项目**显式 administrator 角色**的账号,包含账号或项目成员已经停用的旧任,供补任/更换选择;`memberStatus` 是其项目成员自身状态,`effective` 同时考虑账号、企业成员及项目成员状态。隐式企业管理员不列为可替换项目管理员,企业管理能力不依赖项目角色。该只读维护接口不授予普通项目内部访问。
285
+
286
+ 设置管理员不传 `replaceUserId` 表示补充管理员,已具备身份时幂等;传入表示授予新任并撤销指定旧任的管理员角色。替换对象必须是该范围实际管理员,不得替换自己为自己。新任是有效账号;企业补任可以新增/启用企业成员,项目补任必须有效企业成员并新增/启用项目成员。已有其他角色不变;所有变化和审计在同一事务。此类接口不会启用企业或项目本身。全局账号禁用只改账号状态,不撤销任何角色。
287
+
288
+ 平台账号状态入口不是企业内部业务访问通行证。全局账号原 `locked` 仅保留读取兼容,界面提供启用/停用,平台可显式将其设置为 active 或 disabled。
289
+
290
+ ## 6. 成员与角色端点
291
+
292
+ 下面 `B` 取企业路径 `/companies/:companyId` 或项目路径 `/companies/:companyId/projects/:projectId`;`S` 取 `company` 或 `project`。角色端点还支持 `B=/platform`、`S=platform`。作用域从已验证 URL 推导,请求不能另传 `companyId/projectId/scope` 改变归属。
293
+
294
+ ```ts
295
+ interface RegisterCompanyMemberRequest {
296
+ name: string
297
+ account: string
298
+ password: string
299
+ }
300
+ interface AddProjectMemberRequest {
301
+ userId: string
302
+ }
303
+ interface AssignMemberRolesRequest extends VersionRequest {
304
+ roleIds: string[]
305
+ }
306
+ interface CreateRoleRequest {
307
+ name: string
308
+ description?: string
309
+ permissionKeys?: string[]
310
+ }
311
+ interface UpdateRoleRequest extends VersionRequest {
312
+ name?: string
313
+ description?: string
314
+ }
315
+ interface SetRolePermissionsRequest extends VersionRequest {
316
+ permissionKeys: string[]
317
+ }
318
+ ```
319
+
320
+ | 方法与路径 | 请求 / 返回 | 所需权限与边界 |
321
+ | -------------------------------------------------------- | ------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------- |
322
+ | GET `B/members` | `PageQuery & {status?: EntityStatus}` → `PageResult<MemberRecord>` | `S.members.read` |
323
+ | POST `/companies/:companyId/members` | `RegisterCompanyMemberRequest` → `MemberRecord` | `company.members.add`;直接创建全局账号并加入当前企业,不接收既有 `userId` |
324
+ | POST `/companies/:companyId/projects/:projectId/members` | `AddProjectMemberRequest` → `MemberRecord` | `project.members.add`;只接收所属企业有效成员的稳定 `userId` |
325
+ | PATCH `B/members/:memberId/status` | `StatusRequest` → `MemberRecord` | `S.members.status` |
326
+ | DELETE `B/members/:memberId?expectedVersion=n` | → `DeleteResult` | `S.members.remove` |
327
+ | PUT `B/members/:memberId/roles` | `AssignMemberRolesRequest` → `MemberRecord` | `S.members.roles`;全量替换当前范围角色 |
328
+ | GET `B/roles` | `PageQuery` → `PageResult<RoleRecord>` | `S.roles.read` |
329
+ | GET `B/roles/:roleId` | → `RoleRecord` | `S.roles.read` |
330
+ | POST `B/roles` | `CreateRoleRequest` → `RoleRecord` | `S.roles.create` |
331
+ | PATCH `B/roles/:roleId` | `UpdateRoleRequest` → `RoleRecord` | `S.roles.update` |
332
+ | PUT `B/roles/:roleId/permissions` | `SetRolePermissionsRequest` → `RoleRecord` | `S.roles.permissions` |
333
+ | DELETE `B/roles/:roleId?expectedVersion=n` | → `DeleteResult` | `S.roles.delete`;只能删除未被分配的自定义角色 |
334
+ | GET `B/permissions` | → `PermissionTreeResult` | `S.roles.read` 或 `S.members.roles`;平台为 `platform.roles.read` 或 `platform.accounts.roles` |
335
+
336
+ 成员分配角色弹窗需要角色选项,因此 GET `B/roles` 也允许持有 `S.members.roles`(平台 `platform.accounts.roles`)的用户读取当前范围角色;这不授予编辑角色权限。GET `B/permissions` 只展示当前作用域功能,不返回其他企业/项目授权。
337
+
338
+ 企业直接注册在同一事务中创建全局账号、当前企业成员关系和默认 member 角色;账号冲突或任一步失败不得留下部分数据。密码只参与散列写入,不能进入审计摘要、日志或响应。
339
+
340
+ 企业邀请只确认是新增企业成员的另一条产品入口。邀请对象、是否绑定账号、载体、有效期、状态、接受/拒绝、撤销/重发、发送渠道、DTO、端点、Token、安全、事务、审计和验收标准均待产品确认;确认前不得从现有代码、页面、迁移或测试反向补写本契约,也不得把它们计入现行端点、数据模型或交付范围。
341
+
342
+ 项目添加成员通过组织成员候选接口的 `purpose=addProjectMember` 查询,只返回当前项目所属企业中有效且尚未加入该项目的成员;前端保存并提交 `userId`。候选查询不要求项目管理员取得通用企业成员列表权限。写接口在事务内重新校验账号、企业、企业成员状态和当前项目重复关系,跨企业、停用或已存在关系返回相应业务错误,不能信任客户端曾经看到的候选结果。停用的既有项目成员应走启用而非重复新增。
343
+
344
+ 给用户新增一个角色时:角色作用域须一致,操作者可授予该角色的当前权限;普通角色不得携带管理员专属能力;内置 administrator 的分配与撤销必须验证委派者身份。保留已有未修改的角色不被误判成新增授予。内置 member 可按成员管理权限分配。
345
+
346
+ 修改自定义角色权限:新增权限必须属于 `grantablePermissionKeys`,不得新授予废弃项;已有废弃引用可原样保留,不通过种子或一次普通保存隐式丢失。授予 operation 必须同时包含其页面 read,否则返回 400;取消 page 时服务端同步从最终集合删除所属 operation。目录不写入 `role_permissions`。前端全选/半选仅是这份集合的展示。
347
+
348
+ 普通成员管理不能绕过最后管理员保护。移除企业成员在一个事务中删除其企业角色、全部下属项目角色/成员、最后企业成员记录;重新添加只获得默认 member,不还原已删除角色。停用只改当前关系状态,角色与子关系保留。
349
+
350
+ ## 7. 菜单管理与发布兼容
351
+
352
+ ```ts
353
+ interface CreateMenuRequest {
354
+ expectedVersion: number
355
+ parentId: string | null
356
+ type: MenuNodeType
357
+ name: string
358
+ icon?: string
359
+ sort?: number
360
+ hidden?: boolean
361
+ status?: EntityStatus
362
+ routeKey?: string
363
+ permissionKey?: string
364
+ }
365
+ interface UpdateMenuRequest extends VersionRequest {
366
+ parentId?: string | null
367
+ name?: string
368
+ icon?: string
369
+ sort?: number
370
+ hidden?: boolean
371
+ status?: EntityStatus
372
+ }
373
+ interface FunctionCatalogResult {
374
+ catalogVersion: string
375
+ items: PermissionDefinition[]
376
+ }
377
+ ```
378
+
379
+ | 方法与路径 | 请求 / 返回 | 权限 |
380
+ | -------------------------------------------------- | -------------------------------------- | ----------------------- |
381
+ | GET `/platform/function-catalog?scopeType=S` | → `FunctionCatalogResult` | `platform.menus.read` |
382
+ | GET `/platform/menus?scopeType=S` | → `MenuTreeResult` | `platform.menus.read` |
383
+ | POST `/platform/menus?scopeType=S` | `CreateMenuRequest` → `MenuTreeResult` | `platform.menus.create` |
384
+ | PATCH `/platform/menus/:menuId` | `UpdateMenuRequest` → `MenuTreeResult` | `platform.menus.update` |
385
+ | DELETE `/platform/menus/:menuId?expectedVersion=n` | → `MenuTreeResult` | `platform.menus.delete` |
386
+
387
+ 版本是该 `scopeType` 整棵树的版本。菜单名称 1–100,icon 最多 64,必须为空串或匹配 `^[a-z0-9]+(?:-[a-z0-9]+)*(?:/[a-z0-9]+(?:-[a-z0-9]+)*)*$`;sort 是 0–100000 整数。新增 page 只传已注册 `routeKey`,permissionKey 由目录推导;operation 只传已注册 `permissionKey`,其 routeKey 和所属 page read 由目录推导;directory 二者均不传。创建后绑定和节点 type 不可通过 PATCH 改写,要换功能须通过合法的新建/移除处理,避免将已有授权悄悄变成另一功能。
388
+
389
+ Web 使用 `import.meta.glob('/src/assets/svg/**/*.svg', { eager: true, query: '?react', import: 'default' })` 形成唯一图标注册表。图标选择器、菜单管理列表和导航必须消费同一注册表;SVG 组件统一通过 `SvgIcon` 渲染。单色菜单 SVG 使用 `currentColor`,源文件宽高为 `1em`,由外部字号控制尺寸。既有多色资源可以进入选择器并保留自身颜色。
390
+
391
+ 发布本变更时,数据迁移把旧 Ant Design 图标名映射为语义等价的 SVG key,并按 `routeKey` 为当前空图标页面补齐默认值;未知的合法自定义 key 不覆盖。种子只为新建页面菜单写入功能目录的默认图标,不覆盖迁移后的现有菜单配置。迁移更新受影响作用域的菜单版本。不同 Web 版本暂时不能识别新 key 时只能回退本地图标,不能修改服务端菜单或授权。
392
+
393
+ directory 可包含 directory/page;page 只包含目录定义中属于它的 operation;operation 无子节点。只允许同 scope 树内合法移动,禁止循环、重复 page 绑定、重复 operation 绑定。停用祖先使后代权限全部不可用,恢复祖先不改后代自身状态;隐藏不撤权。页面移动不改变 operation 的固定所属页面。
394
+
395
+ 普通删除不能删除有子节点、被角色授权引用或受保护的节点。保护 `platform.companies`、`platform.accounts`、`platform.roles`、`platform.menus` 页面及其恢复/委派/启用/维护必需操作,保护其祖先:不得停用、隐藏、删除或移动到会失效的位置。首期可以保护上述四个页面的全部 operation,以保证规则清楚且容易验证。
396
+
397
+ 旧 Web 遇到未知 routeKey:过滤页面和全部 operation,然后移除空目录;直接访问未知路由 404。服务端权限和菜单不随旧前端过滤而变化。用户真正加载新前端代码并重新取得 `/access` 后才出现新页面。既有示例页面保留原有开发示例用途,不混入这三棵生产权限菜单,也不能借示例接口绕过新管理接口。
398
+
399
+ ## 8. 废弃权限清理与最小部署证明
400
+
401
+ ```ts
402
+ interface CleanupPreviewItem {
403
+ permissionKey: string
404
+ title: string
405
+ menuIds: string[]
406
+ roleCount: number
407
+ blockedReasons: string[]
408
+ }
409
+ interface CleanupPreview {
410
+ catalogVersion: string
411
+ deploymentId: string | null
412
+ proofDigest: string | null
413
+ eligible: boolean
414
+ blockedReasons: string[]
415
+ items: CleanupPreviewItem[]
416
+ totals: { permissions: number; menus: number; roleAssignments: number }
417
+ }
418
+ interface CleanupRequest {
419
+ permissionKeys: string[]
420
+ proofDigest: string
421
+ }
422
+ interface CleanupResult {
423
+ removedPermissionKeys: string[]
424
+ alreadyCleanedPermissionKeys: string[]
425
+ removedMenuCount: number
426
+ removedRoleAssignmentCount: number
427
+ }
428
+ ```
429
+
430
+ | 方法与路径 | 请求 / 返回 | 权限 |
431
+ | ------------------------------------------- | ---------------------------------- | ----------------------------------------- |
432
+ | GET `/platform/permissions/cleanup-preview` | → `CleanupPreview` | `platform.menus.cleanup` + 平台内置管理员 |
433
+ | POST `/platform/permissions/cleanup` | `CleanupRequest` → `CleanupResult` | 同上;所有候选重新检查,不信任预览结果 |
434
+
435
+ 系统功能目录保留明确的废弃定义(包含 `deprecated: true`),不会通过“本实例没有注册该 key”推断废弃。后端不再使用目标权限、目标功能已下线(对应菜单及有效入口不能访问),并满足部署证明后才可清理。当前第一版没有废弃功能时,预览返回空 items,不能伪造一批业务功能作为演示数据。
436
+
437
+ 首期不引入部署平台或服务发现系统,采用**由运维发布流程提供的受控部署证明文件**。服务端配置 `ACCESS_DEPLOYMENT_PROOF_FILE` 指向只读 JSON;文件不由普通 API 上传、修改,不接受客户端自报“全部升级完成”。它必须来自本系统实际部署清单,覆盖全部对外服务实例正在运行的版本;执行该文件生成/更新的人负责从实际部署环境核对清单,不能由当前进程自行猜测。
438
+
439
+ ```ts
440
+ interface DeploymentProof {
441
+ deploymentId: string // 本次完成部署的唯一标识
442
+ completed: true
443
+ verifiedAt: string
444
+ expiresAt: string // 最长有效窗口 24 小时
445
+ serviceVersions: {
446
+ version: string
447
+ instanceIds: string[] // 此版本全部在用实例,至少一个
448
+ requiredPermissionKeys: string[] // 此版本发布产物中的完整权限依赖清单
449
+ }[]
450
+ }
451
+ ```
452
+
453
+ 每个服务构建提供 `ACCESS_RELEASE_VERSION` 和相应权限依赖清单;证明中的版本不能重复、实例 ID 不能跨版本重复,执行清理的当前版本必须在清单中且依赖清单与本构建一致。未知/不完整依赖清单、未提供证明、未完成部署、过期、目标 key 仍在任一在用版本依赖中均拒绝清理。运维切换实例/回滚前必须撤销旧证明,部署完成重新生成;不能只改客户端预览。此约定是首期明确的运维边界,不能声称文件本身自动发现了实际实例。
454
+
455
+ `proofDigest` 是服务端对验证后证明内容计算的 SHA-256,只用于防止预览与执行用到不同清单,不是客户端签名或可信来源。预览在无证明时仍可列出明确废弃项及阻断原因,`eligible=false`;无候选时不能执行空请求。执行时在管理锁内重新读文件、验证有效性与 digest、核对所有候选及当前角色/菜单引用。
456
+
457
+ 有有效子节点、受保护入口、活动功能或不满足部署条件时,整个请求失败,不部分删除。通过时按角色引用 → 可删除的菜单节点/绑定 → 权限记录顺序在同一事务清理,写入 `permission_cleanup_tombstones`(permissionKey 唯一)并记录审计、递增涉及角色与菜单版本。重复请求中已在 tombstone 的 key 计入 `alreadyCleanedPermissionKeys`,不重复变更;既不在明确废弃目录也不在 tombstone 的 key 拒绝。随后初始化不得重建 tombstone 指向的任何权限或引用。
458
+
459
+ ## 9. 审计端点与字段
460
+
461
+ ```ts
462
+ interface AuditRecord {
463
+ id: string
464
+ actor: UserSummary
465
+ scope: AccessScope
466
+ action: string
467
+ objectType: string
468
+ objectId: string
469
+ summary: Record<string, string | number | boolean | null | string[]>
470
+ requestId: string
471
+ createdAt: string
472
+ }
473
+ interface AuditQuery extends PageQuery {
474
+ action?: string
475
+ actorId?: string
476
+ from?: string
477
+ to?: string
478
+ }
479
+ ```
480
+
481
+ GET `/platform/audit-logs`、`/companies/:companyId/audit-logs`、`/companies/:companyId/projects/:projectId/audit-logs` 返回 `PageResult<AuditRecord>`,分别要求 `platform.audit.read`、`company.audit.read`、`project.audit.read`。日期为 ISO 字符串,`from <= to`;默认不额外限制日期。平台只看 scopeType=platform,企业看本企业 company+project,项目只看本项目。query 搜索 action/objectType/objectId 的公开标识,不提供任意 JSON SQL 筛选。
482
+
483
+ action 使用固定 `company.create/company.status/company.administrator.set/project.create/project.status/project.administrator.set/account.status/account.password.reset/member.add/member.status/member.remove/member.roles/role.create/role.update/role.permissions/role.delete/menu.create/menu.update/menu.delete/permission.cleanup`。同一 action 的实际范围从 scope 区分。平台侧企业创建、账号启停、企业管理员设置、管理员重置密码、菜单和清理写平台事件;内部公司/项目变更写自身事件,目标企业 ID 可以进入平台事件的 summary,但不能据此把该事件归入企业审计。`account.password.reset` 仅在成功时写入,`summary` 只含 `{ result: 'success' }`;两种密码操作的成功与失败安全事件见[修改密码技术契约](../../06.认证与会话/修改密码/技术契约.md)。企业邀请审计动作及字段待产品确认,不属于当前固定 action 集合。
484
+
485
+ 摘要只记录字段白名单,例如 `changedFields`, `fromStatus`, `toStatus`, `roleIds`, `permissionKeys`, `targetUserId`, `companyId`, `replacedUserId`;不记录完整请求体、密码或令牌。操作者姓名/账号保存当时快照,防止后续变化破坏审计可读性。本期记录成功管理变更,失败交由现有异常/服务日志处理,不增加失败审计产品。
486
+
487
+ ## 10. 数据模型与迁移
488
+
489
+ 继续导出到 `apps/server/src/database/schema.ts`,可拆分 access schema 后由该文件 re-export,保证既有 Drizzle schema 入口不变。不得改写已有 `0000/0001` 历史迁移;目标迁移及 journal/snapshot 必须可审阅,并在隔离的现有数据库和空库验证后才能执行。当前仓库完整迁移链尚未满足该条件。
490
+
491
+ | 表 | 关键字段与数据库约束 |
492
+ | ------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
493
+ | `companies` | UUID PK;name/code/description;status enum active/disabled;version int > 0;timestamps;code 唯一 |
494
+ | `projects` | UUID PK;company_id NOT NULL FK companies RESTRICT;name/code/description/status/version/timestamps;UNIQUE(company_id,code)、UNIQUE(company_id,id) |
495
+ | `company_members` | UUID PK;company_id/user_id NOT NULL FKs;status/version/timestamps;UNIQUE(company_id,user_id) |
496
+ | `project_members` | UUID PK;company_id/project_id/user_id NOT NULL;status/version/timestamps;FK(company_id,project_id)→projects(company_id,id);FK(company_id,user_id)→company_members(company_id,user_id);UNIQUE(project_id,user_id) |
497
+ | `roles` | UUID PK;scope_type/company_id/project_id;name/description;builtin nullable enum administrator/member;version/timestamps;合法 scope CHECK;各作用域 name 唯一;各作用域 builtin 非空时唯一 |
498
+ | `user_roles` | user_id/role_id 复合 PK,FK users/roles;分配必须在锁内校验角色作用域与公司/项目成员关系;平台无成员表。成员移除事务先删其相应角色分配再删关系 |
499
+ | `permissions` | key varchar(150) PK;scope_type/kind/title/route_key/page_permission_key/admin_only/deprecated;页面 page_permission_key=null,操作引用同 scope 的页面权限 |
500
+ | `role_permissions` | role_id/permission_key 复合 PK,FK roles/permissions RESTRICT;服务层与集成测试保证同 scope,无目录授权 |
501
+ | `menus` | UUID PK;scope_type/parent_id/type/name/icon/sort/hidden/status/route_key/permission_key/protected;父级 FK RESTRICT;UNIQUE(scope_type,route_key) 部分索引仅 page;UNIQUE(scope_type,permission_key) 非空唯一 |
502
+ | `menu_versions` | scope_type PK,version > 0;为三棵菜单树提供稳定版本记录 |
503
+ | `audit_logs` | UUID PK;actor_user_id FK RESTRICT;actor_account/name 快照;scope_type/company_id/project_id;action/object_type/object_id/summary JSONB/request_id/created_at;scope 合法 CHECK |
504
+ | `permission_cleanup_tombstones` | permission_key PK;cleaned_at/deployment_id;不 FK 到已删除权限 |
505
+ | `access_bootstrap` | singleton PK=1;initialized_admin_user_id FK users、initialized_at;用于一次性平台管理员初始化,不随指定新账号重复提权 |
506
+
507
+ scope CHECK 精确为:platform 两个 ID 均 NULL;company company_id 非 NULL 且 project_id NULL;project 两个 ID 均非 NULL,且复合 FK 指向所属 project。role 同名约束与内置角色唯一约束分别对 platform/company/project 使用 partial unique index,不能依赖 PostgreSQL 默认 NULL 相等语义。成员关系和角色引用的跨作用域服务层约束必须有真实数据库集成测试。
508
+
509
+ 新表 created_at/updated_at 为 timestamptz;审计只有 created_at。必要索引:projects(company_id,status),成员(company_id/user_id)、项目成员(project_id/user_id),user_roles(user_id),role_permissions(permission_key),menus(scope_type,parent_id),audit(scope_type,company_id,project_id,created_at,id)。无企业/项目物理删除接口,不增加级联业务删除。现有 `0003_cute_killmonger.sql` 仍包含已取消的企业父子层级,清理并重新验证前不得执行;企业邀请的数据模型和索引待产品确认,不在当前迁移契约内,现有 `0004_company-member-invitations.sql` 同样不能作为迁移或发布依据。
510
+
511
+ 初始化命令约定为 server 脚本 `access:init --account <已注册完整账号>`,通过现有环境读取数据库/Redis配置,不写任何默认密码。经批准的数据库迁移与目录种子必须可重复;第一次在管理锁内确认 active 账号、创建平台内置角色和三棵全局菜单/权限种子、建立平台管理员并写 access_bootstrap。已有 bootstrap 时,重复同账号只校验/更新系统目录;不同账号拒绝,不能通过删改参数提权。后续种子更新不改变任何用户角色分配,管理员权限按代码目录补齐、member保留基础入口、自定义角色和菜单配置保留,清理 tombstone 必须先过滤。新企业/项目事务按范围创建两个内置角色。
512
+
513
+ 解除 `0003`/`0004` 阻断并完成隔离验证后,目标迁移顺序为备份 → Drizzle migration → 服务端和目录更新 → 前端。当前不得执行仓库完整迁移链,也不得手工跳号、修改迁移历史或用 `db:push` 绕过。未来迁移失败时停止后续发布,按迁移事务回滚或经审阅恢复备份。开发/测试部署证明由运行期临时文件注入,不能在仓库提交真实运维数据或账号密码。
514
+
515
+ ## 11. 事务、锁和会话一致性
516
+
517
+ 首期采用一个明确可验证的 PostgreSQL 管理事务 advisory lock:`pg_advisory_xact_lock(7421, 1)`,仅用于本系统 access 管理命名空间。**所有管理写操作**(资料、状态、成员、角色、授权、菜单、清理、初始化)首先取得该锁,再读取授权和数据,然后业务变更+审计在同一事务提交。锁覆盖本期整个权限依赖图,所以多实例也串行;首期接受管理写入串行的吞吐代价,未来优化为细锁必须维持相同验收,不提前引入另一套分布式锁。
518
+
519
+ 事务采用 PostgreSQL READ COMMITTED;获取 advisory lock 后的下一次查询读取最新已提交状态,再执行账号、上层作用域、成员、管理员身份、页面+操作、资源归属、expectedVersion 校验。不能在拿锁前计算一次权限后把结果带入事务,也不能把 Drizzle 事务中的查询误用外部 db 连接。失败回滚,无成功审计。读取接口不缓存授权,响应构建过程中使用同一事务快照/读取上下文,避免拼接不同用户或作用域数据。
520
+
521
+ 先取得管理锁的写请求允许先完成,撤权等待;撤权先提交则后续请求在锁内重新鉴权并失败。最后管理员数量在同一锁内按变更后的结果计算。企业/项目管理员保护覆盖成员移除/停用/撤角色,平台内置管理员禁用全局账号是企业/项目保护例外,永远不能突破至少一名 active 平台内置管理员。项目有效管理员包含有效企业管理员。
522
+
523
+ 账号登录和禁用还须处理 PostgreSQL 与 Redis 的并发:
524
+
525
+ 1. 每次受保护请求在 Redis Session 验证后查 users 当前状态,非 active 401;包括现有 upload,而不只新管理接口。
526
+ 2. 登录完成密码验证后,在数据库事务中对目标 users 行加共享锁,重新确认 active,再调用现有 SessionStoreService 创建会话,结束事务;密码散列计算在锁外完成。
527
+ 3. 账号状态管理按“管理 advisory lock → 目标 users 行排他锁”顺序,调用现有 `revokeAllForUser` 后写目标状态和审计,再提交。启用也撤销残存旧会话,确保用户必须重新登录。登录只获取用户行锁,不反向申请管理锁,避免死锁。
528
+ 4. Redis 撤销失败则账号状态事务不成功,返回既有 `AUTH.SERVICE_UNAVAILABLE`。若 Redis 已撤销而数据库提交失败,最多导致用户重新登录,不能导致旧权限恢复。这里不声称 Redis 与 PostgreSQL 组成分布式原子事务。
529
+
530
+ 管理接口之外不能新增绕开该用户行锁的 Session 创建路径;否则禁用与登录竞态会让恢复账号后出现旧会话复活。以上实现可复用现有 auth repository/SessionStoreService,不需重写 Cookie/Bearer 或引入 JWT。
531
+
532
+ ## 12. 错误码、前端和验收对照
533
+
534
+ 以下新错误集中在 access 模块 `*.errors.ts`,使用 `AppException`,并加入现有 error-catalog.spec.ts。未知数据库/程序错误按现有全局过滤器返回 500,不把整个流程 catch 成 503。
535
+
536
+ | HTTP | code | 场景 |
537
+ | ---- | ----------------------------------------------------- | -------------------------------------------------------------------- |
538
+ | 400 | `COMMON.VALIDATION_FAILED` | DTO、分页、UUID、类型、未知字段校验 |
539
+ | 400 | `ACCESS.INVALID_PERMISSION_SET` | 未注册/跨 scope/非法页面操作组合、重复授权 |
540
+ | 400 | `ACCESS.INVALID_MENU_STRUCTURE` | 循环、类型父子不合法、跨 scope、重复绑定、未知目录绑定 |
541
+ | 401 | `AUTH.SESSION_TOKEN_MISSING` / `AUTH.SESSION_INVALID` | 沿用既有 token/账号失效;bearerChallenge=true |
542
+ | 403 | `ACCESS.FORBIDDEN` | 当前范围权限不足、管理员身份不足、无权授予、范围/成员/功能停用 |
543
+ | 404 | `ACCESS.NOT_FOUND` | 所有管理资源不存在与跨企业/项目/角色/成员目标统一文案 |
544
+ | 409 | `ACCESS.VERSION_CONFLICT` | expectedVersion 过期 |
545
+ | 409 | `ACCESS.DUPLICATE_RESOURCE` | 同范围编码/角色名称/成员/绑定重复 |
546
+ | 409 | `ACCESS.LAST_ADMINISTRATOR` | 最后有效管理员保护或恢复时没有管理员 |
547
+ | 409 | `ACCESS.BUILTIN_ROLE_IMMUTABLE` | 人工修改/删除内置角色定义 |
548
+ | 409 | `ACCESS.RESOURCE_IN_USE` | 自定义角色仍分配,菜单仍有引用/子节点,清理有有效依赖 |
549
+ | 409 | `ACCESS.PROTECTED_MENU` | 破坏管理恢复入口 |
550
+ | 409 | `ACCESS.CLEANUP_BLOCKED` | 非废弃目标、功能未下线、证明缺失/过期/变更、仍有版本依赖 |
551
+ | 409 | `ACCESS.ALREADY_INITIALIZED` | 初始化参数企图更换平台首位管理员 |
552
+ | 422 | `ACCESS.INVALID_MEMBER_ACCOUNT` | 企业直接注册中的账号条件不符合 |
553
+ | 422 | `ACCESS.INVALID_MEMBER_RELATION` | 管理员或项目成员 `userId` 不属于要求的有效企业成员,或成员关系不可用 |
554
+ | 503 | `AUTH.SERVICE_UNAVAILABLE` | 复用 Session Redis 明确依赖失败语义 |
555
+ | 500 | `COMMON.INTERNAL_SERVER_ERROR` | 未知服务错误;底层信息不公开 |
556
+
557
+ 前端路由 `/login`、`/register`、`/workspaces` 加三套管理布局。登录成功 Cookie 保存 token,跳 `/`,由入口 middleware 获取企业、项目和平台入口:仅有一个项目且没有平台或额外企业管理职责时,直接进入该项目的首个已授权页面;其余情况进入 `/workspaces`。普通企业成员的默认权限不阻止单项目直达;手动访问 `/workspaces` 和具体企业、项目链接不执行默认入口分流。注册成功跳登录并带账号 UI 状态,不保存密码。企业成员新增界面保留“直接注册”和“邀请”两个产品入口;直接注册按本契约实施,邀请入口之后的页面、字段、路由和交互待产品确认,现有邀请管理页与接受页不构成稳定契约。无企业工作空间空态应引导用户联系企业管理员,不预设邀请载体,也不要求提供完整账号供管理员直接挂接。项目成员新增使用 `OrganizationMemberSelector` 的 `purpose=addProjectMember`,选择值固定为 `userId`,不返回组织、岗位或角色标签。工作台只展示当前用户/作用域基本信息和可用入口,不虚构统计 API。权限上下文不持久化,管理 API 默认 `cacheFor:0, shareRequest:false`,可省去首期业务缓存隔离复杂度;仍须在切换/退出/换号取消旧请求并使用用户+scope+请求代次避免迟到响应写回。
558
+
559
+ 403 刷新当前 access 一次,避免递归刷新;401 清 Cookie/用户缓存并回登录;404 显示无资源页,不泄漏其他作用域存在性;409 保留用户输入并提示刷新,不能自动用旧输入覆盖新版本。路由切换、窗口 focus、成功授权变更刷新上下文。菜单路由等待提交期间必须保留旧页面视觉内容并隔离交互,加载层覆盖;目标路由提交后再替换页面,避免卸载 `RouteTransition` 导致视图过渡失去旧快照。父级 scope middleware 获取一次权限上下文,叶子 access middleware 校验页面读权限,布局和按钮消费同一次导航提交的数据,后端始终独立鉴权。middleware 统一位于 `router/middleware`,路由分模块位于 `router/modules`;页面通过 `lazyLoad` 加载,`App.tsx` 统一承载 `RouteTransition`。
560
+
561
+ 15 项需求验收对应:1 企业/项目创建事务;2 scope隔离及企业管理员隐式项目访问;3 目录/页面/操作及接口一致;4 最新授权与停用;5 请求取消/换号;6 唯一约束/最后管理员;7 事务审计;8 既有认证/上传/迁移;9 自身状态保留恢复;10 平台补任与替换;11 内置企业管理员专属创建;12 内置角色目录升级;13 未知routeKey兼容;14 受控证明和事务清理;15 双顺序真实数据库锁验证。
562
+
563
+ 契约/架构负责人独占 `packages/shared`,负责共享类型、纯工具和目录定义并先导出稳定接口;后端独占 `apps/server`,前端独占 `apps/web`,两端引用共享包,不能定义第二份传输 DTO。前端、后端各自测试本范围后由主控联调,验收报告区分通过/失败/环境无法验证,不把跳过数据库或 Playwright 测试记为通过。
564
+
565
+ ## 13. 后续扩展与变更记录
566
+
567
+ - 企业邀请只保留已确认的入口定位;邀请对象、载体、流程、状态及技术协议全部待产品确认。当前代码、页面、自动化测试及 `0004_company-member-invitations.sql` 只能作为未确认实现记录,不能替代产品确认或进入现行交付。
568
+ - 平台全局账号的管理员重置密码已在当前工作树实现,`platform.accounts.reset-password` 仅平台内置管理员可用,上文权限表、接口表和固定审计 action 清单已同步。业务错误、全端撤销和安全事件见[修改密码技术契约](../../06.认证与会话/修改密码/技术契约.md),测试边界见[修改密码测试报告](../../06.认证与会话/修改密码/测试报告.md)。
569
+
570
+ | 日期 | 变更摘要 | 原因 | 影响范围 |
571
+ | ---------- | ----------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------- | ---------------------------------------------------------------------- |
572
+ | 2026-10-08 | 将管理员重置密码纳入当前平台账号操作、接口和固定审计清单,并链接测试边界 | 当前工作树已实现且完成自动化与隔离存储专项 | 平台账号权限、接口与审计清单 |
573
+ | 2026-10-08 | 关联平台账号管理员重置密码的实施中增量,区分待实施权限与当前权限表 | 修改密码契约已确定新增平台管理员操作 | 平台账号权限、接口与审计清单 |
574
+ | 2026-09-19 | 菜单图标契约由服务端图标名白名单调整为安全 SVG key;Web 自动发现本地图标并统一选择、解析和降级,补充旧图标及空值迁移和新菜单默认图标规则 | 前端资源不能由服务端重复维护清单,且需支持新增 SVG 自动进入选择器 | 共享类型、校验、种子、迁移、菜单管理、导航和兼容测试 |
575
+ | 2026-09-18 | 菜单路由等待态保留旧页面视觉内容并隔离交互,目标路由提交后再替换 | 过早卸载 `RouteTransition` 会丢失旧页面视图快照,导致过渡动画消失 | 前端布局、导航等待态、AC-05 与验证要求 |
576
+ | 2026-09-18 | 明确当前完整迁移链受 `0003` 企业层级残留和 `0004` 未确认邀请实现共同阻断,解除前不得执行或绕过 | 目标迁移契约不能被误读为当前仓库已经可以安全迁移 | 数据模型、迁移顺序、初始化前提与发布判断 |
577
+ | 2026-09-18 | 邀请口径纠偏为“只确认产品入口,具体协议待确认”;撤回固定有效期、Token、状态、5 个端点、数据模型、错误码、事务、审计和接受流程等未确认契约 | 现有实现不能反向定义产品协议 | 契约状态、共享 DTO、端点、数据模型、错误码、事务、审计、前端与发布判断 |
578
+ | 2026-09-17 | 企业新增成员由完整账号添加改为直接注册/邀请 | 最新成员边界 | 成员 DTO、POST 企业成员、前端入口、错误与测试 |
579
+ | 2026-09-17 | 项目新增成员改为从所属企业有效成员候选中按 `userId` 添加,并由服务端二次校验 | 避免完整账号歧义、跨企业添加和候选状态竞态 | 候选查询、POST 项目成员、错误与测试 |
580
+ | 2026-09-17 | 企业和项目管理员请求字段统一为 `administratorUserId` | 全局账号名称不唯一,关系必须使用平台唯一 `userId` | 企业/项目创建、管理员设置、选择器回显 |