create-bubbles 0.1.26 → 0.1.27

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 (496) hide show
  1. package/package.json +1 -1
  2. package/template-vp-monorepo-react-nestjs/.agents/rules//345/205/261/344/272/253/344/273/243/347/240/201.md +2 -2
  3. 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
  4. package/template-vp-monorepo-react-nestjs/.codegraph/.gitignore +5 -0
  5. 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
  6. 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
  7. 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
  8. 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
  9. 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
  10. 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
  11. 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
  12. 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
  13. 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
  14. 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
  15. 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
  16. 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
  17. 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
  18. 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
  19. 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 +578 -0
  20. 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
  21. 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
  22. 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
  23. 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
  24. 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
  25. 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
  26. 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
  27. 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
  28. 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
  29. 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
  30. 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
  31. 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
  32. 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
  33. 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
  34. 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
  35. 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
  36. 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
  37. 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
  38. 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
  39. 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
  40. 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
  41. 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
  42. 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
  43. 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
  44. 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
  45. 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
  46. 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
  47. 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
  48. 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
  49. 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
  50. 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
  51. 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
  52. 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
  53. 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
  54. 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
  55. 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
  56. 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
  57. 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
  58. 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
  59. 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
  60. 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
  61. 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
  62. 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 +12 -0
  63. 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 +19 -0
  64. 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 +18 -0
  65. 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 +24 -0
  66. 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
  67. 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
  68. 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
  69. 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
  70. 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
  71. 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
  72. 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 +93 -0
  73. 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 +87 -0
  74. 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 +55 -0
  75. 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 +92 -0
  76. 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 +38 -0
  77. 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 +26 -0
  78. 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 +53 -0
  79. 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 +63 -0
  80. 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
  81. package/template-vp-monorepo-react-nestjs/.spaces/README.md +85 -0
  82. package/template-vp-monorepo-react-nestjs/.spaces//346/226/207/346/241/243/350/247/204/350/214/203.md +97 -0
  83. package/template-vp-monorepo-react-nestjs/AGENTS.md +12 -0
  84. package/template-vp-monorepo-react-nestjs/README.md +3 -27
  85. package/template-vp-monorepo-react-nestjs/apps/server/drizzle/0002_enterprise_access.sql +182 -0
  86. package/template-vp-monorepo-react-nestjs/apps/server/drizzle/0003_cute_killmonger.sql +357 -0
  87. package/template-vp-monorepo-react-nestjs/apps/server/drizzle/0004_company-member-invitations.sql +25 -0
  88. package/template-vp-monorepo-react-nestjs/apps/server/drizzle/0005_menu_svg_icons.sql +54 -0
  89. package/template-vp-monorepo-react-nestjs/apps/server/drizzle/meta/0002_snapshot.json +1801 -0
  90. package/template-vp-monorepo-react-nestjs/apps/server/drizzle/meta/0003_snapshot.json +3511 -0
  91. package/template-vp-monorepo-react-nestjs/apps/server/drizzle/meta/0004_snapshot.json +3713 -0
  92. package/template-vp-monorepo-react-nestjs/apps/server/drizzle/meta/_journal.json +29 -1
  93. package/template-vp-monorepo-react-nestjs/apps/server/drizzle/rollback/0003_organization_backfill.sql +32 -0
  94. package/template-vp-monorepo-react-nestjs/apps/server/package.json +6 -4
  95. package/template-vp-monorepo-react-nestjs/apps/server/src/access-init.ts +45 -0
  96. package/template-vp-monorepo-react-nestjs/apps/server/src/app.controller.ts +3 -0
  97. package/template-vp-monorepo-react-nestjs/apps/server/src/app.module.ts +28 -5
  98. package/template-vp-monorepo-react-nestjs/apps/server/src/app.service.ts +3 -0
  99. package/template-vp-monorepo-react-nestjs/apps/server/src/common/adapters/fastify.adapter.ts +11 -0
  100. package/template-vp-monorepo-react-nestjs/apps/server/src/common/constants/session.constants.ts +9 -0
  101. package/template-vp-monorepo-react-nestjs/apps/server/src/common/decorators/access-policy.decorator.ts +18 -0
  102. package/template-vp-monorepo-react-nestjs/apps/server/src/common/decorators/current-auth.decorator.ts +4 -0
  103. package/template-vp-monorepo-react-nestjs/apps/server/src/common/decorators/public.decorator.ts +3 -0
  104. package/template-vp-monorepo-react-nestjs/apps/server/src/common/exceptions/app.exception.ts +9 -0
  105. package/template-vp-monorepo-react-nestjs/apps/server/src/common/filters/global-exception.filter.ts +38 -5
  106. package/template-vp-monorepo-react-nestjs/apps/server/src/common/security/password-security-event.ts +98 -0
  107. package/template-vp-monorepo-react-nestjs/apps/server/src/config/app.config.ts +3 -0
  108. package/template-vp-monorepo-react-nestjs/apps/server/src/config/database.config.ts +3 -0
  109. package/template-vp-monorepo-react-nestjs/apps/server/src/config/llm.config.ts +3 -0
  110. package/template-vp-monorepo-react-nestjs/apps/server/src/config/queue.config.ts +14 -0
  111. package/template-vp-monorepo-react-nestjs/apps/server/src/config/redis.config.ts +3 -0
  112. package/template-vp-monorepo-react-nestjs/apps/server/src/config/session.config.ts +7 -0
  113. package/template-vp-monorepo-react-nestjs/apps/server/src/config/storage.config.ts +9 -0
  114. package/template-vp-monorepo-react-nestjs/apps/server/src/database/access.schema.ts +394 -0
  115. package/template-vp-monorepo-react-nestjs/apps/server/src/database/db.module.ts +3 -0
  116. package/template-vp-monorepo-react-nestjs/apps/server/src/database/organization.schema.ts +453 -0
  117. package/template-vp-monorepo-react-nestjs/apps/server/src/database/schema.ts +6 -0
  118. package/template-vp-monorepo-react-nestjs/apps/server/src/main.ts +4 -0
  119. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/access/access-http.ts +29 -0
  120. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/access/access.errors.ts +130 -0
  121. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/access/access.guard.ts +63 -0
  122. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/access/access.module.ts +27 -0
  123. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/access/access.service.ts +441 -0
  124. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/access/access.store.ts +68 -0
  125. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/access/access.validation.ts +44 -0
  126. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/access/maintenance/permissions-cleanup.controller.ts +27 -0
  127. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/access/maintenance/permissions-cleanup.service.ts +260 -0
  128. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/access/maintenance/permissions-cleanup.validation.ts +7 -0
  129. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/access/roles/roles.controller.ts +80 -0
  130. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/access/roles/roles.service.ts +249 -0
  131. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/access/roles/roles.validation.ts +24 -0
  132. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/access/seed/access-seed.service.ts +183 -0
  133. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/access/workspaces/workspaces.controller.ts +28 -0
  134. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/access/workspaces/workspaces.service.ts +94 -0
  135. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/access/workspaces/workspaces.validation.ts +5 -0
  136. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/audit/audit.controller.ts +26 -0
  137. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/audit/audit.module.ts +11 -0
  138. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/audit/audit.service.ts +74 -0
  139. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/audit/audit.validation.ts +11 -0
  140. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/auth/auth.controller.ts +25 -0
  141. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/auth/auth.errors.ts +10 -0
  142. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/auth/auth.module.ts +1 -1
  143. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/auth/auth.repository.ts +60 -0
  144. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/auth/auth.service.ts +69 -11
  145. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/auth/dto/register.dto.ts +1 -1
  146. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/auth/guards/session-auth.guard.ts +8 -0
  147. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/auth/password/change-password.dto.ts +17 -0
  148. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/auth/password.service.ts +6 -0
  149. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/auth/session/session-store.service.ts +46 -0
  150. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/auth/session/session-token.service.ts +12 -0
  151. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/auth/session/session.script.ts +7 -1
  152. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/companies/companies.controller.ts +105 -0
  153. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/companies/companies.module.ts +12 -0
  154. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/companies/companies.service.ts +523 -0
  155. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/members/accounts/accounts.controller.ts +72 -0
  156. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/members/accounts/accounts.service.ts +154 -0
  157. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/members/accounts/accounts.validation.ts +8 -0
  158. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/members/accounts/password-reset/password-reset.service.ts +81 -0
  159. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/members/accounts/password-reset/reset-password.validation.ts +13 -0
  160. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/members/administrators/administrators.service.ts +116 -0
  161. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/members/administrators/administrators.validation.ts +1 -0
  162. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/members/invitations/company-member-invitations.controller.ts +69 -0
  163. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/members/invitations/member-invitation-acceptance.controller.ts +23 -0
  164. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/members/invitations/member-invitations.service.ts +344 -0
  165. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/members/invitations/member-invitations.validation.ts +23 -0
  166. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/members/members.controller.ts +88 -0
  167. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/members/members.module.ts +31 -0
  168. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/members/members.service.ts +573 -0
  169. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/members/members.validation.ts +19 -0
  170. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/menus/menus.controller.ts +56 -0
  171. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/menus/menus.module.ts +11 -0
  172. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/menus/menus.service.ts +230 -0
  173. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/menus/menus.validation.ts +30 -0
  174. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/organization/candidates/global-account/global-account-candidates.controller.ts +35 -0
  175. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/organization/candidates/global-account/global-account-candidates.service.ts +109 -0
  176. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/organization/candidates/member-candidates.controller.ts +60 -0
  177. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/organization/candidates/member-candidates.service.ts +939 -0
  178. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/organization/initialization/project-organization-initialization.service.ts +189 -0
  179. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/organization/organization.module.ts +34 -0
  180. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/organization/organization.store.ts +150 -0
  181. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/organization/organization.validation.ts +23 -0
  182. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/organization/positions/positions.controller.ts +160 -0
  183. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/organization/positions/positions.service.ts +636 -0
  184. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/organization/templates/organization-templates.controller.ts +77 -0
  185. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/organization/templates/organization-templates.service.ts +501 -0
  186. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/organization/templates/organization-templates.store.ts +163 -0
  187. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/organization/units/organization-units.controller.ts +187 -0
  188. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/organization/units/organization-units.service.ts +947 -0
  189. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/projects/projects.controller.ts +94 -0
  190. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/projects/projects.module.ts +13 -0
  191. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/projects/projects.service.ts +369 -0
  192. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/task-queue/queue-worker.bootstrap.ts +3 -0
  193. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/task-queue/task-queue.contracts.ts +4 -0
  194. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/task-queue/task-queue.module.ts +5 -0
  195. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/task-queue/task-queue.processor.ts +13 -0
  196. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/task-queue/task-queue.service.ts +9 -0
  197. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/test/db/db.controller.ts +9 -0
  198. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/test/db/db.service.ts +9 -0
  199. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/test/redis/redis.controller.ts +9 -0
  200. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/test/redis/redis.service.ts +18 -0
  201. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/upload/dto/upload-params.dto.ts +1 -1
  202. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/upload/storage/exact-size.transform.ts +14 -3
  203. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/upload/storage/minio-storage.adapter.ts +37 -0
  204. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/upload/storage/storage.port.ts +21 -0
  205. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/upload/upload.constants.ts +9 -0
  206. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/upload/upload.controller.ts +25 -0
  207. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/upload/upload.reponsitory.ts +27 -0
  208. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/upload/upload.service.ts +78 -0
  209. package/template-vp-monorepo-react-nestjs/apps/server/src/modules/upload/utils/object-key.ts +4 -0
  210. package/template-vp-monorepo-react-nestjs/apps/server/src/utils/server-address.ts +6 -0
  211. package/template-vp-monorepo-react-nestjs/apps/server/test/access/access-policy.spec.ts +95 -0
  212. package/template-vp-monorepo-react-nestjs/apps/server/test/access/access.integration.spec.ts +2250 -0
  213. package/template-vp-monorepo-react-nestjs/apps/server/test/access/member-onboarding.validation.spec.ts +78 -0
  214. package/template-vp-monorepo-react-nestjs/apps/server/test/auth/password-operations.spec.ts +433 -0
  215. package/template-vp-monorepo-react-nestjs/apps/server/test/auth/password.integration.spec.ts +300 -0
  216. package/template-vp-monorepo-react-nestjs/apps/server/test/error-catalog.spec.ts +6 -1
  217. package/template-vp-monorepo-react-nestjs/apps/server/test/menus.validation.spec.ts +28 -0
  218. package/template-vp-monorepo-react-nestjs/apps/server/test/organization/organization-domain.spec.ts +260 -0
  219. package/template-vp-monorepo-react-nestjs/apps/server/tsconfig.scripts.json +5 -0
  220. 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
  221. 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
  222. package/template-vp-monorepo-react-nestjs/apps/web/AGENTS.md +17 -8
  223. package/template-vp-monorepo-react-nestjs/apps/web/README.MD +36 -8
  224. package/template-vp-monorepo-react-nestjs/apps/web/index.html +2 -2
  225. package/template-vp-monorepo-react-nestjs/apps/web/package.json +1 -0
  226. package/template-vp-monorepo-react-nestjs/apps/web/src/App.tsx +19 -8
  227. package/template-vp-monorepo-react-nestjs/apps/web/src/api/auth.ts +14 -1
  228. package/template-vp-monorepo-react-nestjs/apps/web/src/assets/svg/accounts.svg +4 -0
  229. package/template-vp-monorepo-react-nestjs/apps/web/src/assets/svg/audit-log.svg +4 -0
  230. package/template-vp-monorepo-react-nestjs/apps/web/src/assets/svg/companies.svg +5 -0
  231. package/template-vp-monorepo-react-nestjs/apps/web/src/assets/svg/dashboard.svg +6 -0
  232. package/template-vp-monorepo-react-nestjs/apps/web/src/assets/svg/home.svg +4 -0
  233. package/template-vp-monorepo-react-nestjs/apps/web/src/assets/svg/members.svg +4 -0
  234. package/template-vp-monorepo-react-nestjs/apps/web/src/assets/svg/menu-item.svg +4 -0
  235. package/template-vp-monorepo-react-nestjs/apps/web/src/assets/svg/menus.svg +6 -0
  236. package/template-vp-monorepo-react-nestjs/apps/web/src/assets/svg/organization-template.svg +4 -0
  237. package/template-vp-monorepo-react-nestjs/apps/web/src/assets/svg/organization.svg +6 -0
  238. package/template-vp-monorepo-react-nestjs/apps/web/src/assets/svg/positions.svg +4 -0
  239. package/template-vp-monorepo-react-nestjs/apps/web/src/assets/svg/profile.svg +5 -0
  240. package/template-vp-monorepo-react-nestjs/apps/web/src/assets/svg/projects.svg +4 -0
  241. package/template-vp-monorepo-react-nestjs/apps/web/src/assets/svg/roles.svg +4 -0
  242. package/template-vp-monorepo-react-nestjs/apps/web/src/components/Brand/Brand.module.css +125 -0
  243. package/template-vp-monorepo-react-nestjs/apps/web/src/components/Brand/Brand.tsx +56 -0
  244. package/template-vp-monorepo-react-nestjs/apps/web/src/components/DraftProTable/DraftProTable.tsx +11 -5
  245. package/template-vp-monorepo-react-nestjs/apps/web/src/components/Icon/SvgAsset/IconSelector.tsx +38 -0
  246. package/template-vp-monorepo-react-nestjs/apps/web/src/components/Icon/SvgAsset/SvgAssetIcon.tsx +14 -0
  247. package/template-vp-monorepo-react-nestjs/apps/web/src/components/Icon/SvgAsset/SvgAssetRegistry.ts +32 -0
  248. package/template-vp-monorepo-react-nestjs/apps/web/src/components/Icon/SvgAsset/index.ts +10 -0
  249. package/template-vp-monorepo-react-nestjs/apps/web/src/components/Icon/svg-icon/SvgIcon.tsx +0 -2
  250. package/template-vp-monorepo-react-nestjs/apps/web/src/components/Loading/PageLoading.tsx +5 -1
  251. package/template-vp-monorepo-react-nestjs/apps/web/src/components/LocaleSwitch/LocaleSwitch.tsx +52 -0
  252. package/template-vp-monorepo-react-nestjs/apps/web/src/components/PasswordActions/ChangePasswordDialog.tsx +90 -0
  253. package/template-vp-monorepo-react-nestjs/apps/web/src/components/PasswordActions/PasswordFields.module.css +12 -0
  254. package/template-vp-monorepo-react-nestjs/apps/web/src/components/PasswordActions/PasswordFields.tsx +54 -0
  255. package/template-vp-monorepo-react-nestjs/apps/web/src/components/PasswordActions/ResetAccountPasswordDialog.tsx +100 -0
  256. package/template-vp-monorepo-react-nestjs/apps/web/src/components/PasswordActions/change-password-session.ts +13 -0
  257. package/template-vp-monorepo-react-nestjs/apps/web/src/components/RouteTransition/RouteTransition.css +60 -0
  258. package/template-vp-monorepo-react-nestjs/apps/web/src/components/RouteTransition/RouteTransition.tsx +44 -0
  259. package/template-vp-monorepo-react-nestjs/apps/web/src/components/Selector/BasicTableSelector/BasicTableSelector.tsx +218 -0
  260. package/template-vp-monorepo-react-nestjs/apps/web/src/components/Selector/BasicTableSelector/BasicTableSelectorSelection.ts +91 -0
  261. package/template-vp-monorepo-react-nestjs/apps/web/src/components/Selector/BasicTableSelector/BasicTableSelectorTypes.ts +60 -0
  262. package/template-vp-monorepo-react-nestjs/apps/web/src/components/Selector/BasicTableSelector/README.md +110 -0
  263. package/template-vp-monorepo-react-nestjs/apps/web/src/components/Selector/BasicTableSelector/index.ts +7 -0
  264. package/template-vp-monorepo-react-nestjs/apps/web/src/components/Selector/GlobalAccountSelect/GlobalAccountSelect.tsx +211 -0
  265. package/template-vp-monorepo-react-nestjs/apps/web/src/components/Selector/GlobalAccountSelect/GlobalAccountSelectTypes.ts +75 -0
  266. package/template-vp-monorepo-react-nestjs/apps/web/src/components/Selector/GlobalAccountSelect/README.md +35 -0
  267. package/template-vp-monorepo-react-nestjs/apps/web/src/components/Selector/GlobalAccountSelect/index.ts +9 -0
  268. package/template-vp-monorepo-react-nestjs/apps/web/src/components/Selector/OrganizationMemberSelector/OrganizationMemberBrowser.tsx +146 -0
  269. package/template-vp-monorepo-react-nestjs/apps/web/src/components/Selector/OrganizationMemberSelector/OrganizationMemberCandidateColumns.tsx +137 -0
  270. package/template-vp-monorepo-react-nestjs/apps/web/src/components/Selector/OrganizationMemberSelector/OrganizationMemberFilterPanel.tsx +209 -0
  271. package/template-vp-monorepo-react-nestjs/apps/web/src/components/Selector/OrganizationMemberSelector/OrganizationMemberSelector.tsx +196 -0
  272. package/template-vp-monorepo-react-nestjs/apps/web/src/components/Selector/OrganizationMemberSelector/OrganizationMemberSelectorTypes.ts +103 -0
  273. package/template-vp-monorepo-react-nestjs/apps/web/src/components/Selector/OrganizationMemberSelector/README.md +8 -0
  274. package/template-vp-monorepo-react-nestjs/apps/web/src/components/Selector/OrganizationMemberSelector/index.ts +13 -0
  275. package/template-vp-monorepo-react-nestjs/apps/web/src/components/Selector/README.md +13 -0
  276. package/template-vp-monorepo-react-nestjs/apps/web/src/components/Selector/index.ts +30 -0
  277. package/template-vp-monorepo-react-nestjs/apps/web/src/config/theme.ts +41 -9
  278. package/template-vp-monorepo-react-nestjs/apps/web/src/hooks/useLatestDialogRequest.ts +71 -0
  279. package/template-vp-monorepo-react-nestjs/apps/web/src/i18n/config.ts +40 -0
  280. package/template-vp-monorepo-react-nestjs/apps/web/src/i18n/index.ts +10 -0
  281. package/template-vp-monorepo-react-nestjs/apps/web/src/i18n/instance.ts +36 -0
  282. package/template-vp-monorepo-react-nestjs/apps/web/src/i18n/ui-locale.ts +30 -0
  283. package/template-vp-monorepo-react-nestjs/apps/web/src/layouts/{BasicLayout.tsx → BasicLayout/index.tsx} +42 -35
  284. package/template-vp-monorepo-react-nestjs/apps/web/src/layouts/WorkspaceLayout/components/WorkspaceNavigationBoundary.tsx +50 -0
  285. package/template-vp-monorepo-react-nestjs/apps/web/src/layouts/WorkspaceLayout/index.tsx +196 -0
  286. package/template-vp-monorepo-react-nestjs/apps/web/src/layouts/WorkspaceLayout/workspace-landing.css +119 -0
  287. package/template-vp-monorepo-react-nestjs/apps/web/src/layouts/WorkspaceLayout/workspace-surfaces.css +110 -0
  288. package/template-vp-monorepo-react-nestjs/apps/web/src/layouts/WorkspaceLayout/workspace.css +223 -0
  289. package/template-vp-monorepo-react-nestjs/apps/web/src/locales/en_US.json +639 -1
  290. package/template-vp-monorepo-react-nestjs/apps/web/src/locales/zh_CN.json +621 -1
  291. package/template-vp-monorepo-react-nestjs/apps/web/src/main.tsx +8 -2
  292. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/api.ts +226 -0
  293. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/audit.tsx +169 -0
  294. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/components/AdministratorDialog.tsx +128 -0
  295. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/components/CleanupDialog.tsx +140 -0
  296. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/components/CompanyHierarchyDialog.tsx +244 -0
  297. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/components/EntityFormDialog.tsx +285 -0
  298. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/components/EntitySelectors/index.ts +6 -0
  299. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/components/EntitySelectors/selector-requests.ts +59 -0
  300. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/components/MemberAffiliations/MemberOrganizationsDialog.tsx +188 -0
  301. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/components/MemberAffiliations/MemberPositionsDialog.tsx +116 -0
  302. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/components/MemberAffiliations/affiliation-loaders.ts +18 -0
  303. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/components/MemberAffiliations/index.ts +5 -0
  304. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/components/MemberOnboarding/AddProjectMemberDialog.tsx +75 -0
  305. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/components/MemberOnboarding/CompanyMemberInvitation/CompanyMemberInvitationDialog.tsx +246 -0
  306. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/components/MemberOnboarding/CompanyMemberInvitation/InvitationRecordsTable.tsx +152 -0
  307. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/components/MemberOnboarding/CompanyMemberInvitation/invitation-link.ts +9 -0
  308. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/components/MemberOnboarding/MemberOnboardingActions.tsx +79 -0
  309. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/components/MemberOnboarding/RegisterCompanyMember/RegisterCompanyMemberDialog.module.css +12 -0
  310. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/components/MemberOnboarding/RegisterCompanyMember/RegisterCompanyMemberDialog.tsx +122 -0
  311. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/components/MemberRolesDialog.tsx +80 -0
  312. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/components/MemberTable/MemberTableColumns.tsx +234 -0
  313. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/components/MemberTable/index.ts +2 -0
  314. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/components/MemberTable/member-candidate-cache.ts +12 -0
  315. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/components/MenuFormDialog.tsx +251 -0
  316. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/components/RoleFormDialog.tsx +73 -0
  317. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/components/RolePermissionsDialog.tsx +185 -0
  318. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/entities.tsx +268 -0
  319. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/home.tsx +67 -0
  320. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/members.tsx +310 -0
  321. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/menus/api.ts +74 -0
  322. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/menus/index.tsx +325 -0
  323. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/profile.tsx +160 -0
  324. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/roles.tsx +173 -0
  325. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/access/use-access.ts +35 -0
  326. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/error/404.tsx +20 -0
  327. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/error/error.tsx +42 -0
  328. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/examples/i18n/index.tsx +20 -38
  329. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/examples/pro-table/components/ProjectFormDialog.tsx +46 -41
  330. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/examples/pro-table/config/columns.tsx +20 -15
  331. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/examples/pro-table/config/index.ts +32 -22
  332. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/examples/pro-table/draft/components/DraftProjectFormDialog.tsx +41 -34
  333. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/examples/pro-table/draft/config/columns.tsx +27 -20
  334. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/examples/pro-table/draft/config/projects.ts +21 -13
  335. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/examples/pro-table/draft/index.tsx +47 -27
  336. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/examples/pro-table/index.tsx +51 -36
  337. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/home/index.tsx +9 -6
  338. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/login/api.ts +3 -0
  339. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/login/index.tsx +62 -82
  340. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/login/login-form.css +199 -0
  341. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/login/login.css +146 -124
  342. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/member-invitations/accept.css +47 -0
  343. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/member-invitations/accept.tsx +143 -0
  344. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/member-invitations/api.ts +20 -0
  345. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/organization/api.ts +91 -0
  346. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/organization/components/MoveOrganizationUnitDialog.tsx +82 -0
  347. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/organization/components/OrganizationBrowser/OrganizationMemberColumns.tsx +87 -0
  348. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/organization/components/OrganizationBrowser/OrganizationMemberHeader.tsx +102 -0
  349. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/organization/components/OrganizationBrowser/OrganizationTreeModel.tsx +59 -0
  350. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/organization/components/OrganizationBrowser/OrganizationTreePanel.tsx +88 -0
  351. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/organization/components/OrganizationBrowser/index.ts +11 -0
  352. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/organization/components/OrganizationBrowser/organization-loaders.ts +47 -0
  353. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/organization/components/OrganizationBrowser/organization-member-filter-loaders.ts +187 -0
  354. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/organization/components/OrganizationMembersDialog.tsx +207 -0
  355. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/organization/components/OrganizationUnitDialog.tsx +110 -0
  356. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/organization/index.tsx +258 -0
  357. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/organization-templates/api.ts +53 -0
  358. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/organization-templates/components/OrganizationTemplateDialog/TemplateDefinitionTabs.tsx +189 -0
  359. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/organization-templates/components/OrganizationTemplateDialog/index.tsx +135 -0
  360. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/organization-templates/components/OrganizationTemplateDialog/types.ts +25 -0
  361. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/organization-templates/index.tsx +201 -0
  362. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/positions/api.ts +81 -0
  363. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/positions/components/PositionFormDialog.tsx +86 -0
  364. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/positions/components/PositionMembersDialog.tsx +102 -0
  365. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/positions/index.tsx +198 -0
  366. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/positions/loaders.ts +35 -0
  367. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/register/api.ts +14 -0
  368. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/register/index.tsx +157 -0
  369. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/workspaces/api.ts +32 -0
  370. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/workspaces/index.tsx +146 -0
  371. package/template-vp-monorepo-react-nestjs/apps/web/src/pages/workspaces/state.ts +24 -0
  372. package/template-vp-monorepo-react-nestjs/apps/web/src/router/AGENTS.MD +6 -0
  373. package/template-vp-monorepo-react-nestjs/apps/web/src/router/index.tsx +2 -46
  374. package/template-vp-monorepo-react-nestjs/apps/web/src/router/lazy-load/index.tsx +26 -0
  375. package/template-vp-monorepo-react-nestjs/apps/web/src/router/middleware/README.md +23 -0
  376. package/template-vp-monorepo-react-nestjs/apps/web/src/router/middleware/auth.ts +6 -0
  377. package/template-vp-monorepo-react-nestjs/apps/web/src/router/middleware/index.ts +4 -0
  378. package/template-vp-monorepo-react-nestjs/apps/web/src/router/middleware/workspace/access.ts +23 -0
  379. package/template-vp-monorepo-react-nestjs/apps/web/src/router/middleware/workspace/data.ts +55 -0
  380. package/template-vp-monorepo-react-nestjs/apps/web/src/router/middleware/workspace/entry.ts +52 -0
  381. package/template-vp-monorepo-react-nestjs/apps/web/src/router/modules/access/page.tsx +20 -0
  382. package/template-vp-monorepo-react-nestjs/apps/web/src/router/modules/auth.tsx +17 -0
  383. package/template-vp-monorepo-react-nestjs/apps/web/src/router/modules/company.tsx +30 -0
  384. package/template-vp-monorepo-react-nestjs/apps/web/src/router/modules/entry.tsx +20 -0
  385. package/template-vp-monorepo-react-nestjs/apps/web/src/router/modules/examples.tsx +23 -0
  386. package/template-vp-monorepo-react-nestjs/apps/web/src/router/modules/fallback.tsx +13 -0
  387. package/template-vp-monorepo-react-nestjs/apps/web/src/router/modules/index.tsx +32 -0
  388. package/template-vp-monorepo-react-nestjs/apps/web/src/router/modules/platform.tsx +27 -0
  389. package/template-vp-monorepo-react-nestjs/apps/web/src/router/modules/project.tsx +28 -0
  390. package/template-vp-monorepo-react-nestjs/apps/web/src/router/page-registry.tsx +94 -0
  391. package/template-vp-monorepo-react-nestjs/apps/web/src/styles/dream.css +34 -0
  392. package/template-vp-monorepo-react-nestjs/apps/web/src/styles/index.css +6 -0
  393. package/template-vp-monorepo-react-nestjs/apps/web/src/types/auto-imports.d.ts +26 -0
  394. package/template-vp-monorepo-react-nestjs/apps/web/src/utils/organization-assignment.ts +66 -0
  395. package/template-vp-monorepo-react-nestjs/apps/web/src/utils/request/core/index.ts +48 -13
  396. package/template-vp-monorepo-react-nestjs/apps/web/src/utils/request/core/utils.ts +5 -0
  397. package/template-vp-monorepo-react-nestjs/apps/web/src/utils/request/index.ts +7 -2
  398. package/template-vp-monorepo-react-nestjs/apps/web/src/utils/request/workspace.ts +82 -0
  399. package/template-vp-monorepo-react-nestjs/apps/web/src/utils/safe-next.ts +36 -0
  400. package/template-vp-monorepo-react-nestjs/apps/web/src/utils/storage/cookie.ts +1 -0
  401. package/template-vp-monorepo-react-nestjs/apps/web/src/utils/storage/session.ts +1 -0
  402. package/template-vp-monorepo-react-nestjs/apps/web/test/i18n-locale.spec.ts +22 -0
  403. package/template-vp-monorepo-react-nestjs/apps/web/test/icon-selector.spec.tsx +23 -0
  404. package/template-vp-monorepo-react-nestjs/apps/web/test/latest-dialog-request.spec.ts +89 -0
  405. package/template-vp-monorepo-react-nestjs/apps/web/test/member-invitation-navigation.spec.ts +34 -0
  406. package/template-vp-monorepo-react-nestjs/apps/web/test/organization-assignment.spec.ts +137 -0
  407. package/template-vp-monorepo-react-nestjs/apps/web/test/password-actions.spec.ts +40 -0
  408. package/template-vp-monorepo-react-nestjs/apps/web/test/password-reset-action.spec.ts +64 -0
  409. package/template-vp-monorepo-react-nestjs/apps/web/test/request.spec.ts +1 -0
  410. package/template-vp-monorepo-react-nestjs/apps/web/test/router/access.spec.ts +136 -0
  411. package/template-vp-monorepo-react-nestjs/apps/web/test/router/config.ts +140 -0
  412. package/template-vp-monorepo-react-nestjs/apps/web/test/router/entry.spec.ts +179 -0
  413. package/template-vp-monorepo-react-nestjs/apps/web/test/router/workspace-data.spec.ts +112 -0
  414. package/template-vp-monorepo-react-nestjs/apps/web/test/selector/global-account-select.spec.ts +311 -0
  415. package/template-vp-monorepo-react-nestjs/apps/web/test/selector/organization-member-selector.spec.ts +454 -0
  416. package/template-vp-monorepo-react-nestjs/apps/web/test/selector/selector-selection.spec.ts +132 -0
  417. package/template-vp-monorepo-react-nestjs/apps/web/test/storage.spec.ts +1 -0
  418. package/template-vp-monorepo-react-nestjs/apps/web/test/tsconfig.json +2 -2
  419. package/template-vp-monorepo-react-nestjs/apps/web/test/workspace-navigation-boundary.spec.tsx +169 -0
  420. package/template-vp-monorepo-react-nestjs/apps/web/test/workspace-navigation.spec.ts +105 -0
  421. package/template-vp-monorepo-react-nestjs/apps/web/test/workspace-requests.spec.ts +174 -0
  422. package/template-vp-monorepo-react-nestjs/apps/web/test/workspaces-password-entry.spec.tsx +71 -0
  423. package/template-vp-monorepo-react-nestjs/apps/web/vite.config.ts +84 -35
  424. package/template-vp-monorepo-react-nestjs/apps/web-vue/package.json +2 -0
  425. package/template-vp-monorepo-react-nestjs/apps/web-vue/src/api/index.ts +1 -0
  426. package/template-vp-monorepo-react-nestjs/apps/web-vue/src/hooks/chart/useEcharts.ts +13 -1
  427. package/template-vp-monorepo-react-nestjs/apps/web-vue/src/layout/default/header/index.vue +1 -0
  428. package/template-vp-monorepo-react-nestjs/apps/web-vue/src/layout/default/index.vue +6 -2
  429. package/template-vp-monorepo-react-nestjs/apps/web-vue/src/router/guard/index.ts +1 -0
  430. package/template-vp-monorepo-react-nestjs/apps/web-vue/src/router/guard/permissionGuard.ts +1 -0
  431. package/template-vp-monorepo-react-nestjs/apps/web-vue/src/router/index.ts +1 -0
  432. package/template-vp-monorepo-react-nestjs/apps/web-vue/src/store/index.ts +1 -0
  433. package/template-vp-monorepo-react-nestjs/apps/web-vue/src/store/modules/user.ts +1 -0
  434. package/template-vp-monorepo-react-nestjs/apps/web-vue/src/types/auto-import.d.ts +2 -0
  435. package/template-vp-monorepo-react-nestjs/apps/web-vue/src/utils/request/core/index.ts +30 -0
  436. package/template-vp-monorepo-react-nestjs/apps/web-vue/src/utils/request/core/utils.ts +5 -0
  437. package/template-vp-monorepo-react-nestjs/apps/web-vue/src/utils/request/index.ts +2 -0
  438. package/template-vp-monorepo-react-nestjs/apps/web-vue/src/views/example/echart/config.ts +1 -0
  439. package/template-vp-monorepo-react-nestjs/apps/web-vue/tsconfig.tsbuildinfo +1 -1
  440. package/template-vp-monorepo-react-nestjs/package.json +1 -8
  441. package/template-vp-monorepo-react-nestjs/packages/i18n/cli/src/command.ts +22 -2
  442. package/template-vp-monorepo-react-nestjs/packages/i18n/cli/src/config.ts +1 -0
  443. package/template-vp-monorepo-react-nestjs/packages/i18n/cli/src/files.ts +1 -0
  444. package/template-vp-monorepo-react-nestjs/packages/i18n/cli/src/load-config.ts +8 -0
  445. package/template-vp-monorepo-react-nestjs/packages/i18n/cli/src/report.ts +2 -0
  446. package/template-vp-monorepo-react-nestjs/packages/i18n/cli/src/scanner.ts +11 -0
  447. package/template-vp-monorepo-react-nestjs/packages/i18n/cli/src/sync.ts +12 -0
  448. package/template-vp-monorepo-react-nestjs/packages/i18n/cli/test/command.test.ts +1 -0
  449. package/template-vp-monorepo-react-nestjs/packages/i18n/cli/test/temporary-directory.ts +5 -0
  450. package/template-vp-monorepo-react-nestjs/packages/i18n/core/src/format.ts +1 -0
  451. package/template-vp-monorepo-react-nestjs/packages/i18n/core/src/i18n.ts +14 -0
  452. package/template-vp-monorepo-react-nestjs/packages/i18n/core/src/storage.ts +8 -0
  453. package/template-vp-monorepo-react-nestjs/packages/i18n/core/src/store.ts +9 -0
  454. package/template-vp-monorepo-react-nestjs/packages/i18n/react/src/index.tsx +5 -0
  455. package/template-vp-monorepo-react-nestjs/packages/i18n/react/src/use-store.ts +3 -0
  456. package/template-vp-monorepo-react-nestjs/packages/i18n/vue/src/index.ts +6 -0
  457. package/template-vp-monorepo-react-nestjs/packages/i18n/vue/src/use-store.ts +3 -0
  458. package/template-vp-monorepo-react-nestjs/packages/shared/package.json +5 -1
  459. package/template-vp-monorepo-react-nestjs/packages/shared/src/index.ts +2 -13
  460. package/template-vp-monorepo-react-nestjs/packages/shared/src/types/access-maintenance.ts +68 -0
  461. package/template-vp-monorepo-react-nestjs/packages/shared/src/types/access-menus.ts +94 -0
  462. package/template-vp-monorepo-react-nestjs/packages/shared/src/types/access-resources.ts +168 -0
  463. package/template-vp-monorepo-react-nestjs/packages/shared/src/types/access.ts +71 -0
  464. package/template-vp-monorepo-react-nestjs/packages/shared/src/types/auth.ts +23 -0
  465. package/template-vp-monorepo-react-nestjs/packages/shared/src/types/index.ts +9 -0
  466. package/template-vp-monorepo-react-nestjs/packages/shared/src/types/organization/models.ts +361 -0
  467. package/template-vp-monorepo-react-nestjs/packages/shared/src/utils/access-catalog.ts +304 -0
  468. package/template-vp-monorepo-react-nestjs/packages/shared/src/utils/access-scope.ts +97 -0
  469. package/template-vp-monorepo-react-nestjs/packages/shared/src/utils/account.ts +1 -0
  470. package/template-vp-monorepo-react-nestjs/packages/shared/src/utils/index.ts +65 -0
  471. package/template-vp-monorepo-react-nestjs/packages/shared/src/utils/organization/contracts.ts +237 -0
  472. package/template-vp-monorepo-react-nestjs/packages/shared/src/utils/record.ts +10 -0
  473. package/template-vp-monorepo-react-nestjs/packages/shared/src/utils/session-terminal.ts +1 -0
  474. package/template-vp-monorepo-react-nestjs/packages/shared/test/access.spec.ts +194 -0
  475. package/template-vp-monorepo-react-nestjs/packages/shared/test/organization.spec.ts +168 -0
  476. package/template-vp-monorepo-react-nestjs/pnpm-workspace.yaml +103 -69
  477. package/template-vp-monorepo-react-nestjs/scripts/enterprise-qa/browser.mjs +696 -0
  478. package/template-vp-monorepo-react-nestjs/scripts/enterprise-qa/http-support.mjs +105 -0
  479. package/template-vp-monorepo-react-nestjs/scripts/enterprise-qa/http.mjs +1091 -0
  480. package/template-vp-monorepo-react-nestjs/scripts/enterprise-qa/legacy-http.mjs +140 -0
  481. package/template-vp-monorepo-react-nestjs/scripts/enterprise-qa/legacy.mjs +196 -0
  482. package/template-vp-monorepo-react-nestjs/scripts/enterprise-qa/runtime.mjs +110 -0
  483. package/template-vp-monorepo-react-nestjs/scripts/with-enterprise-test-env.mjs +80 -0
  484. package/template-vp-monorepo-react-nestjs/src/types/auto-imports.d.ts +60 -0
  485. package/template-vp-react/.vscode/settings.json +8 -1
  486. package/template-vp-react/package.json +10 -10
  487. package/template-vp-react/src/types/auto-imports.d.ts +2 -0
  488. package/template-vp-vue-eslint-vapor/package.json +20 -20
  489. 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
  490. package/template-vp-monorepo-react-nestjs/apps/web/src/layouts/BasicLayout.module.css +0 -17
  491. package/template-vp-monorepo-react-nestjs/apps/web/src/router/modules/.gitkeep +0 -0
  492. package/template-vp-react/.agents/rules/SVG/344/275/277/347/224/250.md +0 -8
  493. package/template-vp-react/AGENTS.md +0 -11
  494. /package/template-vp-monorepo-react-nestjs/apps/web/src/assets/{hero.png → image/hero.png} +0 -0
  495. /package/template-vp-monorepo-react-nestjs/apps/web/src/assets/{react.svg → svg/react.svg} +0 -0
  496. /package/template-vp-monorepo-react-nestjs/apps/web/src/assets/{vite.svg → svg/vite.svg} +0 -0
@@ -0,0 +1,421 @@
1
+ # 企业/项目组织架构、岗位与成员选择器需求文档
2
+
3
+ ## 1. 文档状态与依据
4
+
5
+ - 状态:组织架构主体方案已确认;平台下企业彼此独立。企业成员新增只确认“直接注册”和“邀请”两个产品入口,邀请协议细节尚待产品确认,不能按现有实现宣告完成或通过验收。
6
+ - 日期:2026-09-18。
7
+ - 当前阶段:数据库 `0003` 尚未应用;当前 Schema、Shared、Server、Web、测试及 `0003_cute_killmonger.sql` 仍残留企业间父子层级实现,清理并重新验证后方可迁移。现有邀请代码、页面、自动化测试及 `0004_company-member-invitations.sql` 属于未获产品确认的实现偏差,不进入本专项现行契约或验收结论。
8
+ - 业务真相源:本文;[设计方案](./设计方案.md)与[技术契约](./技术契约.md)必须以本文的当前结论为准。
9
+ - 现有系统背景:[企业、项目与菜单权限管理实施计划](../权限与菜单/需求文档.md)。
10
+ - 本需求文档负责收敛业务目标、范围、规则和可测试验收标准;设计取舍和实现契约分别由同目录设计方案与技术契约承接,不在本文固化未确认的接口或数据库细节。
11
+ - 确认记录:用户于 2026-09-16 确认初版方案并授权实施;2026-09-17 明确平台下企业彼此独立,该决定覆盖初版中的企业间父子设计。
12
+
13
+ ## 2. 背景与现有系统基线
14
+
15
+ 现有系统已经具备平台、企业、项目三级工作空间及 AccessScope,拥有全局账号、企业成员、项目成员、企业/项目角色、菜单权限、作用域鉴权和审计能力。组织能力应建立在这些模型之上,不新增第四种访问作用域,也不替换现有成员与 RBAC 角色。
16
+
17
+ 只读盘点确认了以下实现基线:
18
+
19
+ | 领域 | 当前实现 | 本期衔接点 |
20
+ | ---------- | ------------------------------------------------------------------------------ | ---------------------------------------------------- |
21
+ | 全局账号 | users.id 是全局用户标识;account 全局唯一;name 不唯一 | 所有人员选择与关系最终使用 userId,不以姓名识别人员 |
22
+ | 作用域 | shared 已定义 platform、company、project 三种 AccessScope | 组织能力只使用 company 与 project 作用域 |
23
+ | 成员 | 已有 company_members 与 project_members,项目成员受所属企业成员资格约束 | 组织归属和岗位任职必须绑定既有成员关系 |
24
+ | 权限 | 已有 roles、user_roles、权限目录、路由鉴权和审计 | 组织、岗位本身不授予权限;管理动作继续通过 RBAC 授权 |
25
+ | 企业与项目 | 平台下企业彼此独立;项目保存直接所属 companyId;企业、项目已有启停和管理员规则 | 只扩展企业/项目各自的组织能力,不改变企业模型 |
26
+ | Web 页面 | 企业、项目分别有独立工作空间路由和成员/角色页面 | 新增企业与项目各自的“人员与组织”管理入口 |
27
+ | 选择器 | 已有 BasicTableSelector 与返回全局 userId 的 GlobalAccountSelect | 复用全局账号选择器,新增组织成员选择器 |
28
+ | 组织数据 | 当前没有组织树、岗位、模板或相关接口 | 均为本期新增领域能力 |
29
+
30
+ 当前平台管理员选择已统一以 `userId` 为稳定值;企业普通成员新增只确认“直接注册新账号并加入企业”和“邀请”两个产品入口,项目普通成员新增从所属企业有效成员中按 `userId` 选择。旧的完整账号直接拉入成员契约不再作为当前产品规则。邀请对象、账号绑定方式、载体、有效期、状态、接受/拒绝、撤销/重发、发送渠道及安全与审计规则均待确认,现有邀请实现不得反向定义产品需求。
31
+
32
+ ## 3. 背景问题与产品目标
33
+
34
+ ### 3.1 要解决的问题
35
+
36
+ 1. 企业内部组织与项目执行组织容易混成一棵没有权限边界的通用树,多个独立企业之间也必须保持严格隔离。
37
+ 2. 企业希望维护通用的项目组织标准,但不同项目又需要在创建后独立调整。
38
+ 3. 同一个成员可能同时属于多个组织单元、担任多个岗位,现有成员和角色模型无法表达这些业务关系。
39
+ 4. 岗位、组织归属和权限角色容易被误认为同一概念,导致组织调整时意外改变系统权限。
40
+ 5. 人员选择既需要企业/项目范围、组织、岗位和角色辅助定位,也必须保持全局账号唯一和作用域隔离。
41
+ 6. 后续项目流程需要引用企业组织目标,但当前阶段不应为了未来工作流提前交付一个不完整的审批引擎。
42
+
43
+ ### 3.2 本期目标
44
+
45
+ 1. 在不改变独立企业模型的前提下,建立彼此隔离的企业组织树和项目组织树。
46
+ 2. 提供组织单元创建、维护、移动、整数排序、停用/恢复和成员分配能力。
47
+ 3. 提供与组织单元完全独立的企业岗位库和项目岗位库,支持一人多岗、一岗多人。
48
+ 4. 支持企业成员、项目成员分别加入多个本作用域组织单元,且不存在主归属或默认组织。
49
+ 5. 提供企业维护的项目组织模板,使项目可从标准结构初始化后独立演进。
50
+ 6. 提供可复用的组织成员选择能力,并继续区分全局账号选择、具体成员选择和未来工作流目标选择。
51
+ 7. 沿用现有 AccessScope、成员资格、RBAC、审计及 401/403/404 安全边界。
52
+ 8. 为后续企业目标发布、工作流目标解析和任务级授权保留稳定引用边界,但不在本期实现完整工作流。
53
+
54
+ ### 3.3 成功结果
55
+
56
+ - 管理员能够在对应工作空间维护组织、岗位、成员关系和模板,而不会意外改变成员权限。
57
+ - 同一账号在企业及不同项目中的组织、岗位关系分别维护,跨作用域关系无法写入。
58
+ - 项目可以按明确选择的模板版本初始化,也可以空白创建;之后不会被模板后台静默改写。
59
+ - 选择器能在服务端授权范围内查找具体人员,同名人员和同名组织均可可靠区分。
60
+ - 本期交付不产生“项目小组”、主归属、岗位挂组织、工作流半成品等额外概念。
61
+
62
+ ## 4. 本期范围与明确不做
63
+
64
+ ### 4.1 本期范围
65
+
66
+ | 能力组 | 本期交付 |
67
+ | ---------- | -------------------------------------------------------------------------------- |
68
+ | 企业边界 | 平台下企业彼此独立,沿用现有企业字段与项目直接归属,不新增企业间父子关系 |
69
+ | 企业组织 | 每个企业自己的组织树、组织单元维护、移动、状态、整数 sort、完整路径 |
70
+ | 项目组织 | 每个项目自己的组织树,与企业组织树和其他项目组织树隔离 |
71
+ | 成员关系 | 企业成员多企业组织单元、项目成员多项目组织单元、组织负责人、未归属视图 |
72
+ | 岗位 | 企业/项目平面岗位库、岗位状态、成员多岗位任职 |
73
+ | 组织模板 | 企业维护项目组织模板,分别复制组织结构和项目岗位定义 |
74
+ | 管理页面 | 企业/项目工作空间中的组织架构、岗位、成员管理页面 |
75
+ | 选择器 | 复用 GlobalAccountSelect;新增 OrganizationMemberSelector 及受权限保护的候选查询 |
76
+ | 权限与审计 | 组织、岗位、模板、成员分配动作的权限拆分、作用域校验、事务和审计 |
77
+ | 后续边界 | 稳定组织单元、岗位、成员的 ID、作用域、状态与完整路径查询语义 |
78
+
79
+ ### 4.2 明确不做
80
+
81
+ - 不新增项目小组、协作组或类似实体;稳定结构使用项目组织单元,临时协作由具体业务选择成员。
82
+ - 不建立企业间父子关系,不新增企业间父级、类型、排序、同父名称规范键、层级查询或移动能力。
83
+ - 不设置主归属、默认组织、首选组织或兼任归属;不得根据数组第一项、提交顺序、展示顺序推导特殊组织关系。
84
+ - 岗位不关联组织单元;岗位、模板岗位和任职关系均不保存组织单元字段。
85
+ - 组织单元、岗位不会自动创建、分配或撤销 RBAC 角色。
86
+ - 不实现完整工作流引擎、表单设计器、条件表达式、会签、转交、流程实例和附件授权。
87
+ - 本期不实现 WorkflowTargetSelector、企业目标发布管理、运行时接收人解析或任务级资源授权;这些进入单独的工作流阶段。
88
+ - 不支持跨企业、跨项目移动组织单元。
89
+ - 首期不要求拖拽组织树;移动通过显式选择目标父级和 sort 完成。
90
+ - 不把企业组织树实时映射为项目组织树,不做模板对已有项目的后台自动同步。
91
+ - 不改变现有上传数据的 ownerId 授权模型。
92
+ - 首期不提供组织单元、岗位和模板的物理删除,只提供停用与恢复;成员组织关系和岗位任职仍可按既有解除语义移除,并写入审计。
93
+
94
+ ## 5. 核心概念与已确认产品原则
95
+
96
+ | 概念 | 产品含义 | 权限含义 |
97
+ | -------------- | -------------------------------------------------------- | ------------------------------ |
98
+ | 企业 | 平台下彼此独立的业务与数据边界,拥有独立 companyId | 继续使用 company 作用域 |
99
+ | 企业组织单元 | 企业内部可嵌套的通用组织节点,如事业部、中心、部门、班组 | 不是新作用域,不直接授予权限 |
100
+ | 项目组织单元 | 项目内部可嵌套的执行组织节点 | 不是新作用域,不直接授予权限 |
101
+ | 企业/项目成员 | 全局账号与对应企业/项目的既有成员关系 | 是组织归属和岗位任职的资格前提 |
102
+ | 企业/项目岗位 | 对应作用域中的平面业务任职,如董事、项目经理、资料员 | 不进入组织树,不直接授予权限 |
103
+ | 权限角色 | 现有 RBAC 权限集合 | 决定页面、按钮和接口权限 |
104
+ | 组织模板 | 企业维护的项目组织结构和项目岗位定义快照来源 | 不复制成员、负责人、任职或角色 |
105
+
106
+ 以下原则已经由用户明确,不再作为可选设计:
107
+
108
+ 1. 平台下的企业彼此独立,不存在企业间父子关系,也不发生跨企业组织或权限继承。
109
+ 2. 企业组织树与项目组织树分开,界面可以聚合展示,数据库不建立跨树父子关系。
110
+ 3. 企业成员可加入多个企业组织单元,项目成员可加入当前项目的多个项目组织单元。
111
+ 4. 所有组织成员关系地位相同;没有主归属、默认组织或根据顺序推导的特殊关系。
112
+ 5. 不建设项目小组。
113
+ 6. 企业岗位和项目岗位保留,但岗位不关联组织单元。
114
+ 7. 一名成员可以在同一作用域担任多个岗位,一个岗位可以有多名成员。
115
+ 8. 组织单元 sort 只保存和编辑一个非负整数,不拆分输入、不使用小数。
116
+ 9. 每个组织单元最多一名主要负责人;同一个人可以负责多个组织单元。
117
+ 10. 平台账号以全局 userId 唯一识别,姓名不唯一。
118
+ 11. 组织归属、岗位和权限角色相互独立。
119
+
120
+ ## 6. 核心角色与用户故事
121
+
122
+ | 编号 | 角色 | 用户故事与可观察结果 |
123
+ | ----- | ---------------- | ---------------------------------------------------------------------------------------------------------------------------- |
124
+ | US-01 | 企业组织维护者 | 我可以在当前企业工作空间维护企业组织树,不会修改项目组织树或其他企业的数据。 |
125
+ | US-02 | 项目组织维护者 | 我可以在当前项目工作空间维护项目组织树,不能把节点移动到企业组织树或其他项目。 |
126
+ | US-03 | 成员维护者 | 我可以把一个有效成员分配到多个本作用域组织单元,并为每条关系维护职责;系统不会创建主归属。 |
127
+ | US-04 | 组织负责人维护者 | 我可以为组织单元设置主要负责人;第二名主要负责人会被事务性拒绝,同一人可以负责多个组织单元。 |
128
+ | US-05 | 岗位维护者 | 我可以独立维护企业/项目岗位并为成员批量分配多个岗位;组织变化不会自动改变岗位。 |
129
+ | US-06 | 企业模板维护者 | 我可以维护项目组织模板,模板内的组织结构与项目岗位定义互相独立。 |
130
+ | US-07 | 项目创建者 | 我可以空白创建项目或明确选择企业模板版本初始化;创建后项目组织由项目独立维护。 |
131
+ | US-08 | 业务选人者 | 我可以按可见企业/项目、组织、岗位、权限角色和搜索条件找到具体成员;选择结果以 userId 为核心。 |
132
+ | US-09 | 普通成员 | 我可以在有权查看的页面中看到自己的全部组织和岗位标签,不会被标记为某个“主组织”。 |
133
+ | US-10 | 审计查看者 | 我可以在既有审计边界内查看组织、岗位、模板和成员关系变更,不会在日志中看到密码或 token。 |
134
+ | US-11 | 后续流程设计者 | 后续工作流可以引用稳定的组织单元、岗位和成员目标,但必须另行实现企业发布、解析和任务级授权,不能把组织成员资格当作流程授权。 |
135
+
136
+ ## 7. 功能需求
137
+
138
+ 本节展开已确认原则。后续契约必须完整覆盖这些要求;若产品方案发生变化,应先同步调整本 PRD、验收标准和契约,不能由实现阶段自行偏离。
139
+
140
+ ### FR-01 独立企业边界
141
+
142
+ 1. 平台下的企业彼此独立,继续使用现有 company 作用域和 companyId,不新增其他企业作用域或企业间父子关系。
143
+ 2. 本期不为 companies 新增企业间父级、类型、排序或同父名称规范键,也不新增层级查询、企业移动或相关权限。
144
+ 3. 每个企业独立拥有成员、管理员、角色、组织、数据、审计和项目;任一企业的成员、角色、权限和组织关系不能继承或传播到其他企业。
145
+ 4. 项目始终只归属一个企业并保存直接 companyId,其他企业不会因此获得隐式项目访问权。
146
+ 5. 需要独立成员、权限、数据和项目边界的单位,应建立为平台下的独立企业;同一企业内部的事业群、分公司等汇报层级使用组织单元表达。
147
+
148
+ ### FR-02 企业与项目组织树
149
+
150
+ 1. 每个企业拥有自己的企业组织树,每个项目拥有自己的项目组织树。
151
+ 2. 企业或项目本身作为界面虚拟根,真实顶级组织单元没有持久化的根节点记录。
152
+ 3. 企业组织单元的父级只能是同一企业组织树的组织单元;项目组织单元的父级只能是同一项目组织树的组织单元。
153
+ 4. 组织单元至少包含稳定 ID、所属树、父级、名称、编码、说明、sort、状态和版本;树按父节点懒加载,每次返回一个层级及 `hasChildren`,节点仍返回当前完整路径。
154
+ 5. 组织单元编码在单棵树内唯一,名称在同一父级下唯一;编码和名称均按 `lower(NFKC(trim(value)))` 规范值比较,内部空白不自动折叠。编码接受大小写字母输入,但保存和返回时统一转为小写;名称只去除首尾空白并保留展示大小写。
155
+ 6. 允许不同分支出现同名组织单元;所有选择和展示必须带所属企业/项目及完整路径,不能只显示末级名称。
156
+ 7. 每棵组织树最多 10 层:第一个真实顶级组织单元计为第 1 层,企业/项目虚拟根不计层;创建、移动和模板复制均校验目标节点及其完整子树不得超过第 10 层。
157
+ 8. 组织单元支持创建、编辑、移动、停用和恢复。移动保持 ID 不变,禁止移动到自身或后代。
158
+ 9. 停用组织单元保留节点、成员关系和历史引用;其自身及后代的有效性规则按第 9 节执行。
159
+ 10. 企业组织树、各项目组织树可以在浏览器或选择器中聚合展示,但聚合位置不改变真实父子关系。
160
+
161
+ ### FR-03 组织单元排序
162
+
163
+ 1. 企业与项目组织单元只保存一个整数 sort,允许范围为 0~999999999。
164
+ 2. 前端只显示一个整数输入框,编辑时原值回显并原样提交;拒绝负数、小数和超范围值。
165
+ 3. 排序仅在同一棵树、同一父级下比较,统一按 sort 升序、ID 升序返回。
166
+ 4. 相同 sort 合法,由 ID 保证稳定顺序;修改单个节点不自动重排其他节点。
167
+ 5. 首个同级节点默认 sort 为 1,其余默认为同级最大 sort 加一;达到上限时停止自动递增并要求人工调整。
168
+ 6. 移动时允许明确填写新 sort;未填写时排到目标父级最后,并使用下一个可用整数。
169
+
170
+ ### FR-04 组织成员关系
171
+
172
+ 1. 企业组织关系绑定有效 company_member;项目组织关系绑定有效 project_member。
173
+ 2. 一个成员可以在本作用域拥有多条不同组织单元关系,但同一成员与同一组织单元的关系只能有一条。
174
+ 3. 全部组织关系地位相同;请求和响应不得包含主归属、默认组织字段,后端不得把数组第一项解释为特殊关系。
175
+ 4. 成员可以暂时不属于任何组织单元;“未归属组织”只作为查询和界面的虚拟分组,不创建数据库节点。
176
+ 5. 每条关系保存一个 duty,首期固定为 member、leader 或 deputy;同一成员在同一组织单元只有一条关系,因此不能同时占用多个 duty。
177
+ 6. 每个组织单元最多一名主要负责人;唯一限制建立在组织单元上,不能限制同一个人负责多个组织单元。
178
+ 7. 同一组织单元可以有多名 deputy;leader 和 deputy 都必须是当前组织单元成员,设置职责不会自动授予管理员角色。
179
+ 8. 组织关系同时支持“按成员替换其全部组织单元”和“按组织单元替换其全部成员”。按组织单元保存只影响该单元,保留每名成员在其他单元的关系;两种方向均在同一事务内完成,任一跨作用域、重复关系或负责人冲突都使整次提交失败,空数组分别表示解除该成员全部组织关系或清空该单元全部成员。
180
+ 9. 组织关系变化不会自动创建、删除或修改成员的 RBAC 角色和岗位任职。
181
+ 10. 首期不保存、不接收、不返回 memberSort,也不在界面开放成员手工排序;成员列表默认按 duty 优先级 leader、deputy、member,再按成员关系 ID 升序稳定返回。
182
+
183
+ ### FR-05 独立岗位
184
+
185
+ 1. 企业岗位只属于一个企业,项目岗位只属于一个项目;岗位不属于组织树。
186
+ 2. 岗位是平面列表,不设置父级,也不保存组织单元 ID、树 ID或模板组织节点 ID。
187
+ 3. 岗位至少包含稳定 ID、作用域、名称、编码、说明、状态和版本。
188
+ 4. 企业岗位任职绑定企业成员,项目岗位任职绑定项目成员;一个成员可以多岗,一个岗位可以多人。
189
+ 5. 同一成员不能重复担任同一岗位,跨企业、跨项目任职必须被拒绝。
190
+ 6. 组织归属和岗位任职分别维护、分别提交、分别审计;任意一方的新增、移动、停用或移除不自动修改另一方。
191
+ 7. 岗位不会自动映射现有权限角色,也不能仅凭岗位推导某个组织单元中的任职。
192
+ 8. 岗位编码和岗位名称都在各自企业或项目作用域内唯一;唯一性按 lower(NFKC(trim(value))) 的规范值比较,内部空白保留且不自动合并。岗位名称只去除首尾空白并保留展示大小写;岗位编码接受大小写字母输入,但保存和返回时统一转为小写。
193
+ 9. 岗位任职同时支持“按成员替换其全部岗位”和“按岗位替换其全部成员”。按岗位保存只影响该岗位,保留每名成员的其他岗位;两种方向均原子提交,空数组分别表示解除该成员全部任职或清空该岗位全部任职。
194
+
195
+ ### FR-06 项目组织模板
196
+
197
+ 1. 模板属于一个企业,用于初始化该企业直接所属项目的项目组织,而不是实时引用企业组织树。
198
+ 2. 模板分别维护组织单元结构和项目岗位定义;模板岗位不关联模板组织单元。
199
+ 3. 项目初始化请求固定使用 blank 或 template 两种模式。blank 模式不得提交模板 ID/版本;template 模式必须同时提交模板 ID 和精确版本,模板必须属于项目直接企业且处于有效状态。
200
+ 4. 复制组织单元名称、编码、层级和 sort;模板组织单元不单独维护状态,模板中存在的节点初始化为 active。复制岗位名称、编码、说明和状态;模板岗位是平面定义,允许 disabled 岗位复制为项目中的 disabled 岗位,项目后续可独立启用。新项目中的组织单元与岗位分别生成新 ID。
201
+ 5. 模板不复制真实成员、负责人、组织成员关系、岗位任职或权限角色。
202
+ 6. 项目创建后独立维护;模板后续修改或停用不自动改写已有项目。
203
+ 7. 来源模板节点和来源模板岗位分别记录各自来源,不建立岗位与组织单元的映射。
204
+ 8. 企业最多有一个有效默认模板;前端可在新建项目时预选它,但后端只按请求中的显式模式处理,不根据默认模板静默推断。
205
+ 9. 存量迁移只为缺少组织树的既有企业和项目补建空树记录,不创建组织单元、岗位或成员关系;迁移按作用域唯一键保证幂等,并能按迁移批次回滚仅由本次迁移新增且仍为空的树。
206
+ 10. 模板替换必须显式提交完整定义和 isDefault;设置新的默认模板时,旧默认模板也生成保留完整子项的下一版本、递增版本并写审计,避免旁路修改绕过乐观锁。
207
+
208
+ ### FR-07 组织成员选择器
209
+
210
+ 1. GlobalAccountSelect 只服务于有权搜索平台账号的场景,例如平台开通企业或由平台设置企业管理员;稳定值为 userId,不向普通企业或项目操作者开放平台账号浏览。
211
+ 2. 企业侧新增企业成员只确认两条产品入口:直接注册新账号并加入企业,或发起邀请;不提供全平台列表或按完整账号直接拉入既有账号。“邀请”在本阶段仅表示入口名称,邀请对象、是否绑定账号、载体、有效期、状态、接受/拒绝、撤销/重发、发送渠道、DTO、端点、Token、安全、事务、审计和验收标准均待产品确认。现有代码、页面、自动化测试及 `0004_company-member-invitations.sql` 只能证明实现曾被制作,不能作为现行需求或验收依据。
212
+ 3. 项目新增成员使用 OrganizationMemberSelector 的 `addProjectMember` 场景,只查询所属企业的有效成员并排除已经属于当前项目的人;选择值和提交值均为 `userId`,后端写入时再次校验企业成员资格、状态和重复关系。
213
+ 4. 通用 OrganizationMemberSelector 只从调用者当前可见的既有企业成员或项目成员中选择一个或多个具体成员,不能借此发现或创建尚未加入作用域的账号。
214
+ 5. 组件在表单中表现为 Select 风格字段,点击后打开弹窗式组织浏览器;不把企业、项目、多层组织树、岗位、角色和搜索结果塞入普通下拉菜单。
215
+ 6. 选择器由业务注入当前调用场景和候选查询,不自行决定接口地址、权限范围或保存行为;组织成员维护、岗位成员分配和添加项目成员使用不同 purpose,岗位维护者只需岗位查看与分配权限,不隐式依赖组织查看权限。
216
+ 7. 左侧可按可见作用域、组织架构、岗位或权限角色筛选,右侧选择具体人员;点击组织单元只筛选人员,不把组织单元本身作为成员选择值。
217
+ 8. 企业工作空间只有具备 `company.projects.read` 时才可读取本企业项目身份,并继续按调用者的实际项目可见性逐项目裁剪;项目组织、岗位、角色标签及筛选分别要求目标项目的 `project.organization.read`、`project.positions.read`、`project.roles.read`,不能仅凭企业项目查看权限返回。项目工作空间只查看当前项目,不展示企业目标或同企业其他项目组织。
218
+ 9. 搜索由服务端执行,支持姓名或完整账号;结果按全局 userId 去重,同一人只显示一行并聚合可见身份、组织、岗位、必要角色和状态。
219
+ 10. 姓名不作为唯一标识;人员行至少显示姓名、完整账号、来源企业/项目和状态。
220
+ 11. 同名组织单元必须显示“企业/项目 + 完整路径”;组织标签和岗位标签分开展示,交叉筛选不会生成持久关系。
221
+ 12. 停用账号、停用成员或停用作用域显示状态和禁选原因,不静默变成可选。
222
+ 13. 选择器稳定值统一为 userId;企业/项目作用域由调用候选与保存动作的 URL 决定,候选中的项目身份只用于权限裁剪后的展示、筛选和辨识,不作为持久化选择值。需要修改特定项目关系时必须在该项目 URL 下提交,不能由客户端在请求体中自报 scope。
223
+ 14. 除项目添加成员这一明确业务动作外,通用选择操作本身不创建成员、组织关系、岗位任职或角色授权。
224
+ 15. WorkflowTargetSelector 与组织目标联合类型留到工作流专项,不并入本期具体成员选择器。
225
+
226
+ ### FR-08 管理页面
227
+
228
+ 1. 企业和项目分别从自己的工作空间进入“人员与组织”,页面内部不维护第二套企业/项目作用域状态。
229
+ 2. 页面以“组织架构、岗位、成员”作为并列入口;岗位不挂在组织树节点下。
230
+ 3. 组织架构页提供树、全部成员、未归属组织、组织详情、负责人、成员表和创建/编辑/移动/停用/恢复操作。
231
+ 4. 岗位页使用平面列表,展示名称、编码、状态和任职人数;岗位表单不提供组织单元字段。
232
+ 5. 成员页展示成员在当前作用域的全部组织和岗位标签,不突出第一个组织,也不拼接未保存的“组织-岗位”关系。
233
+ 6. 成员分配中,组织归属和岗位任职分区编辑;修改一组不会自动修改另一组。
234
+ 7. 组织单元表单只提供一个 sort 整数输入框;首期移动使用显式弹窗,不要求拖拽。
235
+
236
+ ### FR-09 权限、事务与审计
237
+
238
+ 1. 查看组织、维护结构、移动组织、分配成员、维护岗位、分配岗位和维护模板应按能力拆分,不能只靠页面是否显示进行授权。
239
+ 2. 后端继续按登录态、账号状态、作用域与成员资格、功能权限、资源归属的顺序校验;URL 参数不是授权依据。
240
+ 3. 企业、项目、组织单元、成员、岗位和模板的所有写操作必须同时校验资源所属作用域。
241
+ 4. 跨企业或跨项目资源与不存在资源继续统一返回 404;作用域内已识别的权限不足返回 403。
242
+ 5. 按成员或按组织单元/岗位的批量关系替换、负责人变更、模板复制和相关成功审计在同一事务内提交。
243
+ 6. 组织单元、岗位和模板使用版本校验避免过期编辑覆盖;具体冲突响应由共享契约统一。
244
+ 7. 组织、岗位、模板及成员关系的创建、编辑、移动、排序、状态、分配和移除写入现有作用域审计。
245
+ 8. 审计记录操作者、作用域、对象、关键变更前后值和 requestId,不记录密码、token 或不必要的完整业务数据。
246
+
247
+ ## 8. 权限边界
248
+
249
+ ### 8.1 角色边界
250
+
251
+ - 平台管理员继续通过现有平台入口维护彼此独立的企业;平台身份不自动成为任何企业成员,也不通过本期组织能力获得跨企业数据权限。
252
+ - 企业管理员或具备对应企业权限的角色只能管理当前企业的组织、岗位、模板和成员关系;管理其他企业必须进入目标企业并具备该企业的显式权限。
253
+ - 项目管理员或具备对应项目权限的角色只能管理当前项目组织、岗位和成员关系,不能修改企业组织树。
254
+ - 普通成员只获得角色明确授予的查看或操作能力;加入组织、担任岗位、成为负责人均不自动授予管理员权限。
255
+
256
+ ### 8.2 能力拆分草案
257
+
258
+ 现有权限目录的最终 key 在契约阶段统一。本期至少保持以下能力互相独立:
259
+
260
+ | 作用域 | 能力 |
261
+ | -------- | ---------------------------------------------------------------------- |
262
+ | 平台 | 沿用现有独立企业创建、编辑和管理员设置;本期不新增企业间父子关系权限 |
263
+ | 企业 | 查看组织、创建组织单元、更新/停用组织单元、移动组织单元、分配组织成员 |
264
+ | 企业 | 查看岗位、创建岗位、更新/停用岗位、分配岗位成员 |
265
+ | 企业 | 查看与维护项目组织模板 |
266
+ | 项目 | 查看组织、创建组织单元、更新/停用组织单元、移动组织单元、分配组织成员 |
267
+ | 项目 | 查看岗位、创建岗位、更新/停用岗位、分配岗位成员 |
268
+ | 候选查询 | 按调用场景读取最小成员、组织、岗位或角色摘要 |
269
+
270
+ 设计真相源已给出 company.organization、company.position、project.organization、project.position 等权限建议。组织模板的准确权限 key、内置管理员自动授权及菜单节点由契约阶段结合现有 ACCESS_PERMISSION_CATALOG 定稿,不能由前后端分别命名。
271
+
272
+ ## 9. 生命周期规则
273
+
274
+ | 对象/操作 | 必须保留 | 本期行为 |
275
+ | -------------------- | ------------------------------------------ | ---------------------------------------------------------------------------------------------------- |
276
+ | 移动组织单元 | 组织单元 ID、成员关系、岗位独立性 | 仅同一棵树内移动;当前 fullPath 随结构更新 |
277
+ | 停用组织单元 | 节点、下级节点、成员关系、历史审计 | 自身及受无效祖先影响的下级不参与新候选;不自动删除关系 |
278
+ | 恢复组织单元 | 原节点和关系 | 重新参与后续有效查询,不改写历史审计 |
279
+ | 停用岗位 | 岗位、任职关系、历史审计 | 不参与新的有效候选;保留任职关系 |
280
+ | 恢复岗位 | 原岗位和任职 | 重新参与后续有效查询 |
281
+ | 停用成员 | 组织关系、岗位任职、角色按现有成员规则保留 | 不再作为有效候选;恢复后按当前保存关系参与查询 |
282
+ | 解除组织/岗位关系 | 历史审计 | 删除对应关系记录,不删除成员、组织单元或岗位;批量解除继续遵守事务和作用域校验 |
283
+ | 移除项目成员 | 历史审计 | 同一事务清理该项目成员的项目组织关系、岗位任职、负责人关系和项目角色 |
284
+ | 移除企业成员 | 历史审计及其他企业中的独立关系 | 同一事务清理本企业组织、岗位、负责人和角色,并按现有规则清理本企业直接所属项目中的项目成员及关联关系 |
285
+ | 修改/停用/恢复模板 | 已创建项目自己的组织与岗位 | 停用后不能用于新项目初始化,恢复后按当前有效版本重新可选;任何变更都不自动同步或删除项目数据 |
286
+ | 创建项目 | 既有项目创建事务边界 | 按明确的空白/模板选择初始化组织与岗位;任一步失败整体回滚 |
287
+
288
+ 组织单元、岗位和模板首期均无物理删除入口或删除接口;对这些稳定资源的“删除”请求统一引导为停用。只有成员组织关系和岗位任职等可重建关系按既有解除语义删除关系记录。
289
+
290
+ 组织单元停用时,任一祖先无效都会使当前节点不作为有效候选。管理者仍可查看、编辑和恢复停用节点及其后代,但不能在停用父节点下新建节点,也不能把有效节点移动到停用父节点下。
291
+
292
+ 全量替换关系时,既有停用成员、停用组织单元或停用岗位的关系可以原样保留或解除。按成员提交空数组表示解除该成员在当前关系类型下的全部关系;按组织单元或岗位提交空数组表示清空当前资源的全部关系。停用成员不能新增组织关系或岗位任职,也不能把既有职责升级为 deputy/leader;其既有组织职责只允许原样保留、移除或按 leader → deputy → member 的方向降级。停用或受无效祖先影响的组织单元同样不能新增成员或升级职责,停用岗位不能新增任职。
293
+
294
+ ## 10. 分阶段交付
295
+
296
+ | 阶段 | 交付内容 | 阶段完成标准 |
297
+ | --------------------- | ------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------- |
298
+ | 0. PRD 确认(已完成) | 确认本期边界、方案项和验收标准 | 用户于 2026-09-17 明确企业彼此独立,保留企业/项目各自组织能力 |
299
+ | 1. 共享契约与数据库 | 组织树、组织单元、成员关系、岗位、任职、模板类型与迁移 | 空库和现有库迁移可审阅;作用域、关系唯一、组织循环、整数 sort、主要负责人唯一等约束测试通过 |
300
+ | 2. 后端组织能力 | 企业/项目组织、岗位、成员分配、模板、候选查询和审计 | 服务端独立阻止跨作用域、重复关系、过期版本、非法移动和越权 |
301
+ | 3. 前端管理能力 | 企业/项目“人员与组织”页面、组织树、岗位列表、成员关系和模板管理 | 不依赖直接调用接口即可完成本期管理流程,表单与错误状态可理解 |
302
+ | 4. 组织成员选择器 | OrganizationMemberSelector、服务端分页/搜索、回显和禁选原因 | 可见范围、userId 去重、完整路径、跨页回显和状态处理正确 |
303
+ | 5. 集成与验收 | 迁移、权限、事务、接口、Web 关键流程和回归测试 | 第 11 节逐项有通过证据,构建和项目检查通过 |
304
+ | 后续工作流专项 | 企业目标发布、WorkflowTargetSelector、规则解析、接收人快照、异常转交、任务级资源授权 | 单独 PRD 和契约确认后实施,不作为本期组织能力完成条件 |
305
+
306
+ 本期需要稳定组织单元、岗位和成员目标所需的 ID、作用域、状态及 fullPath 查询语义。企业目标发布关系和任务级授权表不在本期落地,避免在没有流程生命周期与授权模型时交付不可用半成品。
307
+
308
+ ## 11. 可测试验收标准
309
+
310
+ 以下标准把当前已确认方案直接表达为可测试行为,并作为契约设计与后续实现验收的强制输入。若任一方案调整,必须同步改写对应功能需求、验收标准和契约。
311
+
312
+ 1. **AC-01 全局人员标识**:准备两个同名账号后,所有组织和岗位分配均以不同 userId 正确区分;任何接口都不以姓名作为唯一键。
313
+ 2. **AC-02 作用域保持**:交付后 AccessScope 仍只有 platform、company、project;组织单元和岗位不会产生新的工作空间或访问作用域。
314
+ 3. **AC-03 独立企业模型**:companies 继续使用现有 companyId、name、code、status、version 等企业字段;数据库、共享类型、接口和页面均不存在新增的企业间父级、类型、排序、同父名称规范键或其他企业作用域。
315
+ 4. **AC-04 无企业间树能力**:平台企业仍按现有列表方式管理,不新增父子查询、父级选择、企业移动、层级摘要或相关权限;现有企业创建和编辑行为不要求层级资料。
316
+ 5. **AC-05 跨企业隔离**:企业 A 的成员、管理员、角色、组织、岗位、模板和项目数据不会因任何组织关系自动出现在企业 B;跨企业资源继续按不可见处理。
317
+ 6. **AC-06 项目直接归属**:项目只保存一个直接 companyId,项目组织、岗位、成员和模板校验均以该企业为边界,其他企业不会因此获得隐式归属或访问权。
318
+ 7. **AC-07 企业项目分树**:同一企业及其项目分别查询到独立组织树;组织树先查询顶级节点,再以 parentId 懒加载直接子节点并返回 hasChildren;企业节点不能成为项目节点父级,项目节点也不能成为企业节点父级。
319
+ 8. **AC-08 跨树写入拒绝**:跨企业、跨项目创建父子关系或移动组织单元时返回统一的资源不可见结果,原树保持不变。
320
+ 9. **AC-09 组织命名、深度与路径**:同树重复编码或同父级经 `lower(NFKC(trim(value)))` 规范化后同名被拒绝,编码输入统一以小写保存和返回;不同分支允许同名且返回所属企业/项目与完整路径;顶级真实节点计第 1 层,创建、移动或模板复制后超过 10 层时整次操作失败。
321
+ 10. **AC-10 整数排序**:sort 为 15 时接口与数据库保存 15;负数、小数和大于 999999999 的值被拒绝,同级始终按 sort 升序、ID 升序返回。
322
+ 11. **AC-11 默认排序**:首个同级组织单元默认 sort 为 1,后续默认使用当前同级最大值加一;达到上限时不产生溢出值。
323
+ 12. **AC-12 移动排序**:组织单元移动到同树其他父级时保持 ID;明确 sort 按提交值保存,未提交时排在目标同级最后;移动、重命名或状态变更后,已加载节点及全部受影响后代不会继续显示旧 fullPath、depth 或 effective。
324
+ 13. **AC-13 多组织关系**:同一企业成员可以加入多个企业组织单元,同一项目成员可以加入当前项目多个项目组织单元,企业与各项目的关系互不覆盖。
325
+ 14. **AC-14 无主归属**:组织分配请求、响应、数据库和界面均不存在主归属或默认组织;交换提交数组顺序不会改变任一关系语义。
326
+ 15. **AC-15 关系唯一与默认顺序**:按成员或按组织单元批量保存均原子完成,按单元保存不会覆盖成员在其他单元的关系;重复提交同一成员与同一组织单元的关系不会产生两条记录,跨作用域关系整批失败且不留下部分数据;请求、响应和数据库均无 memberSort,成员候选标签返回 membershipId 与 duty,单组织成员视图按 leader、deputy、member 后再按关系 ID 稳定返回。
327
+ 16. **AC-16 主要负责人唯一**:同一组织单元设置第二名主要负责人时整次写入失败;同一个人可以成功成为多个组织单元的主要负责人。
328
+ 17. **AC-17 负责人职责与资格**:duty 只接受 member、leader、deputy;非当前组织单元成员不能成为主要或副负责人,同一单元允许多个 deputy 但最多一个 leader,设置职责不会新增管理员角色或权限。
329
+ 18. **AC-18 未归属视图**:没有任何组织关系的有效成员出现在“未归属组织”虚拟分组中,数据库不存在对应虚拟组织单元记录。
330
+ 19. **AC-19 岗位完全独立**:岗位定义、模板岗位和岗位任职请求/响应不包含 organizationUnitId、treeId 或 templateUnitId;传入此类字段时明确拒绝。
331
+ 20. **AC-20 多岗位与唯一规则**:同一成员可同时担任多个岗位,一个岗位可包含多名成员;按成员或按岗位批量保存均原子完成,按岗位保存不覆盖成员的其他岗位;重复任职和跨作用域任职被拒绝;同作用域内岗位 code 和 name 经 NFKC、首尾去空格和不区分大小写比较后分别唯一,code 接受大小写输入但保存和返回为小写。
332
+ 21. **AC-21 组织岗位解耦**:移动、停用或移除一条组织关系不会自动修改岗位任职;修改岗位任职也不会改变组织归属或角色。
333
+ 22. **AC-22 模板初始化方式**:blank 模式携带模板 ID/版本或 template 模式缺少任一字段均失败;template 模式引用跨企业模板时按资源不可见返回 404,引用当前企业内已停用/不可用模板或版本不匹配模板时分别返回约定业务错误;模板输入的缺失父节点、自引用或环按请求校验失败,超过 10 层按深度错误失败;UI 预选默认模板不改变服务端显式模式语义。
334
+ 23. **AC-23 模板复制边界**:模板初始化只复制组织结构和独立岗位定义并生成新 ID;模板组织单元均以 active 初始化,模板岗位按定义状态复制;不复制成员、负责人、任职和 RBAC 角色。
335
+ 24. **AC-24 项目独立演进**:项目创建后修改或停用来源模板,不会自动新增、更新、移动或删除项目中的组织单元和岗位。
336
+ 25. **AC-25 初始化与存量迁移事务**:模板复制任一步失败时,项目、项目成员、管理员授权、组织树、岗位及成功审计全部回滚;存量迁移重复执行不产生重复树,回滚只删除本批次新增且仍为空的树,不猜测成员组织关系或岗位。
337
+ 26. **AC-26 页面作用域**:企业和项目分别从自己的工作空间进入人员与组织页面,页面内部不存在第二套企业/项目切换;快速切换工作空间时不会显示上一作用域的数据。
338
+ 27. **AC-27 组织成员候选范围**:OrganizationMemberSelector 只返回调用者可见的既有成员;企业场景读取项目身份先要求 `company.projects.read`,再按项目可见性及每个项目的组织/岗位/角色读取权限逐项裁剪标签和筛选能力,不能凭企业项目查看权限泄露项目标签;项目场景只返回当前项目成员,不返回同企业其他项目或尚未加入作用域的账号。
339
+ 28. **AC-28 弹窗搜索与去重**:Select 风格字段打开弹窗式组织浏览器;按姓名或完整账号搜索时由服务端分页返回,同一 userId 在多个可见身份命中时只显示一行并聚合标签。
340
+ 29. **AC-29 同名信息展示**:同名人员显示完整账号和来源作用域,同名组织显示完整路径;组织标签与岗位标签保持独立。
341
+ 30. **AC-30 禁选状态**:停用账号、停用成员或停用作用域的候选显示明确禁选原因,不能被用于新增或升级关系;既有停用关系仍可原样保留、解除或按约定降级职责;按成员保存空数组会解除该成员的全部对应关系,按组织单元或岗位保存空数组会清空当前资源的全部成员关系;未知或越权 ID 不能绕过前端直接写入。
342
+ 31. **AC-31 账号新增与全局选择边界**:只有平台授权场景使用 GlobalAccountSelect 并以 userId 为值;企业侧只展示直接注册和邀请两个产品入口,且无法枚举平台账号。当前只验收直接注册入口及其既有规则;邀请入口之后的对象、流程、状态和技术协议待确认,不计入本期通过条件。项目侧只可从所属企业有效成员中选择尚未加入者并提交 userId,后端二次校验。
343
+ 32. **AC-32 权限能力拆分**:仅有组织查看权限的用户不能创建、移动或分配成员;仅有岗位查看权限的用户不能修改岗位,具备岗位查看与分配权限的维护者可通过岗位 purpose 选择成员且不需要组织查看权限;前端隐藏与服务端拒绝一致。
344
+ 33. **AC-33 资源归属保护**:修改组织、岗位、模板和关系的 Repository 查询同时约束公司/项目归属;跨作用域 ID 与不存在 ID 均返回 404。
345
+ 34. **AC-34 生命周期与清理**:组织单元、岗位和模板没有物理删除接口,只能停用/恢复;解除组织关系或岗位任职仅删除对应关系并审计;移除项目成员或企业成员时按第 9 节事务清理本作用域关联,其他企业的独立关系不受影响。
346
+ 35. **AC-35 审计一致性**:每次成功的创建、编辑、移动、排序、状态和关系变更都有同事务审计;设置新默认模板时,被自动取消默认的旧模板也递增版本、复制完整组织单元/岗位子项到下一版本并写审计;失败或回滚操作没有成功审计,日志不包含密码或 token。
347
+ 36. **AC-36 排除范围验证**:数据库、共享类型、接口和页面中不存在企业间父子关系、项目小组、主归属、岗位-组织持久关联、企业目标发布或可执行的工作流引擎;企业目标发布与任务级授权整体后置,后续专项首个推荐方向为“项目 → 所属企业”,不计入本期完成范围。
348
+
349
+ ## 12. 接口草案
350
+
351
+ 本节只描述资源与业务动作,方便下一阶段划分模块;不确定最终 URL、HTTP 方法、DTO、返回包装、错误码或数据库表。所有请求和返回类型必须在 [技术契约](./技术契约.md) 中统一,不能直接把本节当成接口契约。
352
+
353
+ | 资源范围 | 查询动作 | 写动作 |
354
+ | ---------------- | ---------------------------------------------------------- | ------------------------------------------------ |
355
+ | 企业组织单元 | 查询树/子节点/路径/状态/成员摘要 | 创建、编辑、移动、设置状态、设置 sort |
356
+ | 项目组织单元 | 查询当前项目树/子节点/路径/状态/成员摘要 | 创建、编辑、移动、设置状态、设置 sort |
357
+ | 企业成员组织关系 | 按成员或组织查询关系、查询未归属成员 | 按成员或组织单元批量替换企业组织关系、调整职责 |
358
+ | 项目成员组织关系 | 按成员或组织查询关系、查询未归属成员 | 按成员或组织单元批量替换项目组织关系、调整职责 |
359
+ | 企业岗位 | 分页查询岗位、详情、任职人员 | 创建、编辑、设置状态、按岗位或成员批量替换任职 |
360
+ | 项目岗位 | 分页查询岗位、详情、任职人员 | 创建、编辑、设置状态、按岗位或成员批量替换任职 |
361
+ | 项目组织模板 | 查询企业模板、模板版本、组织结构和岗位定义 | 创建、编辑、设置状态、设置默认模板 |
362
+ | 项目初始化 | 读取可选模板摘要 | 创建项目时按空白或指定模板版本初始化 |
363
+ | 企业成员新增 | 展示直接注册与邀请两个入口;邀请详情待确认 | 直接注册并加入企业;邀请相关写操作待产品确认 |
364
+ | 项目成员候选 | 查询所属企业有效成员并排除当前项目既有成员 | 按 `userId` 添加项目成员,服务端二次校验资格 |
365
+ | 组织成员候选 | 在既有可见成员内按作用域、组织、岗位、角色和关键词分页查询 | 除添加项目成员场景外,选择器不负责创建成员或关系 |
366
+ | 全局账号候选 | 仅平台授权场景按关键词查询账号、按 userId 回显 | 无;继续由 GlobalAccountSelect 使用 |
367
+ | 审计 | 按现有作用域查询组织相关事件 | 随业务事务写入,不提供绕过业务规则的独立写接口 |
368
+
369
+ 后续工作流专项预计新增“企业目标发布”“项目可用企业目标”“目标解析”“任务参与者”“任务级资源授权”等资源与动作。本期既不暴露这些写动作,也不把企业通讯录直接开放给项目。
370
+
371
+ ## 13. 风险与方案确认记录
372
+
373
+ ### 13.1 主要风险
374
+
375
+ | 编号 | 风险 | 控制方式 |
376
+ | ---- | ------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------ |
377
+ | R-01 | 企业组织树和项目组织树在聚合界面中被误认为一棵可跨树移动的真实树 | 所有节点携带作用域和树类型,后端分别校验真实父子关系 |
378
+ | R-02 | 组织归属、岗位和权限角色在页面中同时展示,用户误以为会自动联动 | 分区维护、独立保存、标签分栏,并在关键操作说明“不改变权限” |
379
+ | R-03 | 批量关系替换和主要负责人唯一在并发下出现部分写入 | 数据库唯一约束、固定事务边界、锁内复查和同事务审计 |
380
+ | R-04 | 大企业组织树和成员候选一次加载导致性能和信息泄露 | 树懒加载、服务端分页/搜索、最小字段返回、服务端裁剪可见范围 |
381
+ | R-05 | 模板版本变化覆盖在建项目 | 项目复制快照,提交明确版本,项目创建后完全独立 |
382
+ | R-06 | 旧成员接口按 account 添加,与当前直接注册/邀请入口/userId 选择边界冲突 | 保持旧入口退出;直接注册与项目成员 userId 选择按已确认规则复验,邀请实现隔离为偏差并等待产品确认 |
383
+ | R-07 | 现有数据库已有企业和项目但没有组织树 | 迁移策略必须明确补建空树、失败回滚和重复执行方式 |
384
+ | R-08 | 为未来流程过早落地发布或授权表,形成不可验收的半成品 | 工作流能力单独立项,本期只稳定可引用资源及查询语义 |
385
+
386
+ ### 13.2 已确认方案
387
+
388
+ 用户于 2026-09-16 确认初版组织方案;2026-09-17 明确平台下企业彼此独立。后者为最新决定,原企业间父子关系、排序及同父企业名称规则全部失效。当前确认方案如下:
389
+
390
+ | 决策域 | 当前结论 |
391
+ | ------------ | ----------------------------------------------------------------------------------------------------------------------- |
392
+ | 企业边界 | 平台下企业彼此独立;沿用原有企业字段和项目直接 companyId,不新增企业间父子关系及其接口、权限或约束 |
393
+ | 组织与岗位 | 企业/项目各有独立组织树;三种职责、最多 10 层、无 memberSort;岗位为独立平面列表 |
394
+ | 模板与迁移 | blank/template 显式初始化;存量只补幂等、可回滚的空组织树 |
395
+ | 页面与选择器 | Select 字段打开弹窗;平台管理员使用全局账号选择;企业成员直接注册/邀请,其中邀请协议待确认;项目成员从企业有效成员选择 |
396
+ | 生命周期 | 组织单元、岗位和模板只停用/恢复;组织关系和任职可按既有语义解除 |
397
+ | 后续工作流 | 企业目标发布和任务授权整体后置;首个方向为项目流转到所属企业 |
398
+
399
+ ## 14. 阶段门槛
400
+
401
+ 本需求文档中的独立企业、企业/项目组织树及成员入口选择已通过产品确认门;企业邀请仅确认入口存在,具体协议尚未通过确认门。当前实现与现行结论仍有两类发布阻断,继续交付前必须:
402
+
403
+ 1. 从当前 Schema、Shared、Server、Web、测试及 `0003_cute_killmonger.sql` 中移除企业间父子关系专属字段、接口、权限、约束、错误码、查询、移动、父级选择、展示类型和企业间排序行为。
404
+ 2. 将现有邀请代码、页面、自动化测试及 `0004_company-member-invitations.sql` 标记并隔离为未获确认的实现偏差;产品确认完整邀请协议前,不得迁移、发布或计入本专项契约与验收证据。
405
+ 3. 完成上述同步后,重新执行 Shared、Server、Web、迁移与静态检查,并核对文档中的端点和字段统计。
406
+
407
+ 数据库 `0003` 尚未应用。在以上同步和验证完成前不得执行该迁移;若以后需要跨企业管理,应另行编写 PRD 和技术契约。
408
+
409
+ ### 14.1 待确认项
410
+
411
+ - 企业邀请必须另行确认邀请对象、账号绑定方式、载体、有效期、状态、接受/拒绝、撤销/重发、发送渠道、DTO、端点、Token、安全、事务、审计和验收标准。
412
+ - 在上述协议确认并回写现行需求、设计和契约前,不得以现有实现或其他专项文档中的邀请细节作为默认产品规则;同时不得恢复旧的完整账号直接添加方式。
413
+
414
+ ### 14.2 变更记录
415
+
416
+ | 日期 | 变更摘要 | 原因 | 影响范围 |
417
+ | ---------- | ------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------- | -------------------------------------------- |
418
+ | 2026-09-18 | 纠偏企业邀请口径:只确认“邀请”入口,具体协议全部回到待确认;现有邀请代码、页面、自动化及 `0004` 记为实现偏差 | 产品未确认邀请对象、流程及技术协议,不能由现有实现反向定义需求 | FR-07、AC-31、成员能力、阶段门槛、联调与测试 |
419
+ | 2026-09-18 | 明确当前 Schema、Shared、Server、Web、测试及 `0003` 仍残留企业层级实现 | 区分目标契约与实际实现状态,避免误判为已清理 | 发布阻断、迁移、复验范围 |
420
+ | 2026-09-17 | 取消企业之间的父子层级,企业在平台下彼此独立 | 最新企业边界确认 | 需求、契约、数据库、接口、权限、UI、测试 |
421
+ | 2026-09-17 | 企业成员改为直接注册/邀请;项目成员改为从所属企业有效成员中按 `userId` 选择 | 最新成员新增边界 | FR-07、AC-31、成员接口、选择器和测试 |
@@ -1,7 +1,7 @@
1
1
  # 上传改造方案
2
2
 
3
- > 状态:讨论稿,尚未实施
4
- > 基线日期:2026-09-02
3
+ > 状态:讨论稿,尚未实施;第 2 节保留并校正 2026-09-02 的历史基线
4
+ > 基线日期:2026-09-02;当前事实复核:2026-09-17
5
5
  > 适用范围:apps/server、PostgreSQL、MinIO、Nginx
6
6
  > 本文目标:把当前分片上传改造成“有长期文件记录、具备公司/项目归属、完成后返回标准文件信息、最终文件可经 Nginx 匿名只读访问”的完整方案。
7
7
 
@@ -36,7 +36,7 @@
36
36
 
37
37
  - 永久文件记录与上传会话拆分。
38
38
  - companyId、projectId 的传递、校验和持久化。
39
- - 分片上传接口补齐及完成响应调整。
39
+ - 现有分片上传接口与新增归属字段、文件记录及完成响应的兼容调整。
40
40
  - fileId、fileUrl、文件名、后缀、大小等字段定义。
41
41
  - MinIO 公共只读 Bucket。
42
42
  - Nginx 文件代理。
@@ -54,7 +54,7 @@
54
54
 
55
55
  ## 2. 当前实现事实
56
56
 
57
- 以下内容来自当前源码,不代表目标状态。
57
+ 以下内容已按 2026-09-17 源码复核,不代表目标状态。原方案中“没有 company、project、membership 模型”以及“上传模块尚未接通”的描述已经过期,现按当前事实修正。
58
58
 
59
59
  | 项目 | 当前状态 | 影响 |
60
60
  | ------------- | --------------------------------------------------- | ------------------------------------------------ |
@@ -65,14 +65,10 @@
65
65
  | MinIO Bucket | uploads,anonymous policy 为 none | 普通 Nginx 匿名反代会得到 AccessDenied |
66
66
  | MinIO 端口 | 9000、9001 映射到宿主机 | 生产环境不应直接暴露 |
67
67
  | Nginx | 当前仓库没有文件代理配置 | /files/\*\* 尚不存在 |
68
- | 公司/项目模型 | 当前 schema 中没有 company、project、membership 表 | 无法可靠校验 companyId、projectId |
68
+ | 公司/项目模型 | 已有 companies、projects、company_members、project_members | 上传模块尚未接入这些模型,仍未校验 companyId、projectId |
69
69
 
70
- 当前上传模块还存在以下接通问题,应在正式改造第一阶段处理:
70
+ 当前上传模块已经具备 Controller 五个路由、UploadModule 注册、`initiate()` 主流程和独立会话参数 DTO。仍需在正式改造中处理:
71
71
 
72
- - UploadController 目前只有初始化接口。
73
- - UploadService.initiate() 没有进入真正的新建逻辑,实际逻辑位于误拼的 initate()。
74
- - 当前没有 upload.module.ts,AppModule 也没有导入上传模块。
75
- - UploadSessionParamsDto 错误使用了包含 partNumber 的参数 Schema。
76
72
  - abort() 的部分成功路径没有返回统一响应。
77
73
  - initiate-mutipart-upload.dto.ts、upload.reponsitory.ts 存在文件名拼写问题。
78
74
  - 当前缺少上传模块专项测试。
@@ -668,20 +664,17 @@ MVP 至少应:
668
664
  - 确认缓存和撤回时效。
669
665
  - 确认是否存在需要迁移的历史上传数据。
670
666
 
671
- ### 阶段 1:补齐 company/project 权限事实来源
667
+ ### 阶段 1:接入已有 company/project 权限事实来源
672
668
 
673
- - 建立 company、project、membership 模型或接入已有服务。
674
- - 确保可以从 projectId 校验 companyId。
675
- - 建立统一的公司/项目权限检查。
669
+ - 复用现有 companies、projects、company_members、project_members 模型及访问控制能力。
670
+ - 从 projectId 反查并校验 companyId,不能只信任客户端参数。
671
+ - 将现有公司/项目成员资格与上传权限检查接入上传初始化、查询、分片、完成和取消流程。
676
672
 
677
- 在此阶段完成前,不应仅靠新增两个 DTO 字段就把 companyId、projectId 写入数据库。
673
+ 现有模型并不等于上传模块已经完成归属校验。在本阶段完成前,不应仅靠新增两个 DTO 字段就把 companyId、projectId 写入数据库。
678
674
 
679
- ### 阶段 2:修复上传模块基线
675
+ ### 阶段 2:收尾上传模块基线
680
676
 
681
- - 合并 initiate/initate。
682
- - 补齐 Controller 路由。
683
- - 创建并注册 UploadModule。
684
- - 修正参数 DTO。
677
+ - 保留并回归验证当前已有的五个 Controller 路由、UploadModule、`initiate()` 主流程和独立会话参数 DTO。
685
678
  - 统一 abort 响应。
686
679
  - 修正相关文件名拼写及引用。
687
680
  - 添加当前行为回归测试。
@@ -1,7 +1,7 @@
1
1
  # 上传文件定时清理:给前端开发者的 NestJS + BullMQ 实现教程
2
2
 
3
3
  > 本文是动手实现教程,代码需要你按步骤写入项目;更新本文不代表业务代码已经实现。
4
- > 基线:2026-09-05 的 `apps/server`,PostgreSQL + Drizzle + MinIO,公共队列沿用 [README](./README.md)。
4
+ > 基线:2026-09-05 的 `apps/server`,PostgreSQL + Drizzle + MinIO,公共队列沿用 [公共队列设计方案](../../03.任务队列/公共队列/设计方案.md)。
5
5
  > 最终效果:后端每分钟自动扫描,找到过期且没有分片正在上传的会话,逐个释放 MinIO 中的未完成分片,并保存清理结果。
6
6
 
7
7
  ## 先理解最终效果
@@ -69,7 +69,7 @@ NestJS 启动:向 Redis 注册一条固定的周期规则
69
69
 
70
70
  当前仓库已声明 `bullmq` 和 `@nestjs/bullmq` 依赖,并已有公共队列文件。开始前先检查基础能力是否跑通;如果你还在较早的代码版本上,按基础篇补齐即可,不必重复创建已有文件。
71
71
 
72
- 对照 [公共队列 README](./README.md),确认下面这些文件存在,并看到 `system.queue-smoke.v1` 被 Worker 成功处理,再继续本篇:
72
+ 对照 [公共队列设计方案](../../03.任务队列/公共队列/设计方案.md),确认下面这些文件存在,并看到 `system.queue-smoke.v1` 被 Worker 成功处理,再继续本篇:
73
73
 
74
74
  ```text
75
75
  apps/server/src/config/queue.config.ts
@@ -231,20 +231,19 @@ export const uploadPartLeases = pgTable(
231
231
 
232
232
  一片正在上传,就有一条租约。唯一索引保证同一会话同一分片不会被两次请求同时占用。不同分片仍能并行。现有 Service 已检查 `partNumber` 范围,登记租约放在参数校验之后。
233
233
 
234
- ### 3.3 生成并执行迁移
234
+ ### 3.3 生成迁移并等待全仓阻断解除
235
235
 
236
236
  ```powershell
237
237
  vp run --filter server db:generate
238
238
  ```
239
239
 
240
- 打开新生成的 `apps/server/drizzle/*.sql`,确认包含新增字段、表和索引,没有意外删除旧字段。然后在本地开发数据库执行:
240
+ 打开新生成的 `apps/server/drizzle/*.sql`,确认包含新增字段、表和索引,没有意外删除旧字段。当前仓库完整迁移链受企业层级残留 `0003` 和未确认邀请实现 `0004` 阻断,不得执行 `db:migrate`、手工跳号或使用 `db:push` 绕过。两项阻断解除并完成隔离验证后,按[数据库迁移指南](../../05.运行维护/数据库迁移/操作指南.md)执行经审阅的迁移,再运行:
241
241
 
242
242
  ```powershell
243
- vp run --filter server db:migrate
244
243
  vp run --filter server db:studio
245
244
  ```
246
245
 
247
- Studio 应能看到新结构。`db:generate` 只生成 SQL,`db:migrate` 才修改数据库;只改 TypeScript 不会自动建表。
246
+ 届时 Studio 应能看到新结构。`db:generate` 只生成 SQL,不会修改数据库;只改 TypeScript 同样不会自动建表。
248
247
 
249
248
  ## 第 4 步:共用一把短事务锁
250
249
 
@@ -1444,7 +1443,7 @@ vp run --filter server build
1444
1443
 
1445
1444
  至少持续观察扫描次数、候选数、清理成功数、最终失败 Job、最老未处理记录和长期 `completing` 记录。原始 SDK 错误可能包含连接和存储信息,公共日志只记录安全元数据;Redis 内的失败 Job 也应限权访问并按基础篇设置保留上限。
1446
1445
 
1447
- 上线已有服务时,先迁移数据库,保持清理预览模式,部署完所有支持分片租约的新 API/Worker,排空旧实例及旧在途上传,再启用实际清理。新旧版本混跑时,旧 API 不登记租约,后台无法知道它正在上传,不能提前打开实际清理。
1446
+ 全仓迁移阻断解除并完成隔离验证后,上线已有服务时才先执行经审阅的数据库迁移,保持清理预览模式,部署完所有支持分片租约的新 API/Worker,排空旧实例及旧在途上传,再启用实际清理。新旧版本混跑时,旧 API 不登记租约,后台无法知道它正在上传,不能提前打开实际清理。
1448
1447
 
1449
1448
  本教程使用租约、封口、结果确认和重复补偿处理常见并发与故障。生产还需验证数据库断连、进程暂停超过租约、存储慢请求及实例强杀等情况,并配置请求超时和告警,不能仅凭一次本地成功宣称所有故障已覆盖。
1450
1449
 
@@ -1462,4 +1461,10 @@ vp run --filter server build
1462
1461
  - [ ] 重启不会累积重复规则,停用能删除已有规则。
1463
1462
  - [ ] 完成了测试及 PostgreSQL、Redis、MinIO 实际联调。
1464
1463
 
1465
- 参考:[公共队列基础篇](./README.md)、[上传教程的过期清理说明](../04.upload.md#第-18-步过期清理和生产安全)、[BullMQ Job Schedulers](https://docs.bullmq.io/guide/job-schedulers)。如果以后实施了 [files 表上传改造](../05.上传改造方案/README.md),还需同步该新模型的文件状态;本文代码以当前只有 upload_sessions 的实现为准。
1464
+ 参考:[公共队列基础篇](../../03.任务队列/公共队列/设计方案.md)、[上传教程的过期清理说明](../分片上传/实施教程.md#第-18-步过期清理和生产安全)、[BullMQ Job Schedulers](https://docs.bullmq.io/guide/job-schedulers)。如果以后实施了 [files 表上传改造](../上传改造/设计方案.md),还需同步该新模型的文件状态;本文代码以当前只有 `upload_sessions` 的实现为准。
1465
+
1466
+ ## 变更记录
1467
+
1468
+ | 日期 | 变更摘要 | 影响范围 |
1469
+ | ---------- | ------------------------------------------------------------------------------------------ | -------------------- |
1470
+ | 2026-09-18 | 标明当前仓库完整迁移链受 `0003`/`0004` 阻断,上传清理迁移在阻断解除前只生成和审阅、不执行 | 迁移、联调与上线顺序 |