瀏覽代碼

📝 docs(epic-008): 创建Server和Web多租户集成史诗文档

- 基于史诗007已完成的多租户包基础
- 设计将当前单租户系统直接改为多租户系统
- 按照现有包集成模式实现,无需动态切换
- 多租户模块包直接依赖认证模块的租户上下文管理
- 为后续按需拼装不同系统提供基础

🤖 Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
yourname 1 月之前
父節點
當前提交
3a36f4ced6
共有 1 個文件被更改,包括 357 次插入0 次删除
  1. 357 0
      docs/prd/epic-008-server-web-multi-tenant-integration.md

+ 357 - 0
docs/prd/epic-008-server-web-multi-tenant-integration.md

@@ -0,0 +1,357 @@
+# Epic-008: Server和Web多租户集成 - Brownfield Enhancement
+
+## Epic Goal
+
+将当前的单租户系统直接改为多租户系统,基于史诗007已完成的多租户包,在server和web中集成完整的租户数据隔离和租户管理功能,为后续按需拼装单租户或多租户系统提供基础。
+
+**核心目标:直接改造现有单租户系统为多租户系统,按照现有包集成模式实现。**
+
+## Epic Description
+
+### Existing System Context
+
+**Current relevant functionality:**
+- 史诗007已完成11个多租户业务包的复制和26个前端管理界面包的创建
+- 现有server使用单租户包路由(如`@d8d/user-module`),支持基础的用户、认证、文件等模块
+- 多租户认证模块包(`@d8d/auth-module-mt`)中已实现租户上下文管理,在认证中间件中设置`c.set('tenantId', user.tenantId)`
+- web应用已集成用户管理UI包(`@d8d/user-management-ui`),展示包集成模式
+- web中routes.tsx使用`import { UserManagement } from '@d8d/user-management-ui'`模式
+- web中api_init.ts使用`userClientManager.init('/api/v1/users')`初始化客户端
+- 共享包(shared-crud、shared-types、shared-utils)在两套系统中复用
+- 数据库已支持多租户表结构(带_mt后缀的表)
+
+**Current limitations:**
+- server只能运行单租户模式,不支持多租户
+- web应用只有用户管理使用包模式,其他管理界面仍为本地实现
+- 缺乏租户上下文管理和租户数据隔离
+- 认证系统不支持多租户用户隔离
+- 前端路由不支持租户感知
+
+**Technology stack:**
+- Backend: Node.js, TypeScript, Hono, TypeORM, PostgreSQL
+- Frontend: React 19, TypeScript, TanStack Query, React Hook Form
+- Authentication: JWT, Redis session management
+- Database: PostgreSQL with tenant isolation
+- Package Management: pnpm workspace
+
+**Integration points:**
+- 现有server路由注册机制
+- 认证中间件和用户上下文
+- 数据库连接和实体管理
+- 前端API客户端和路由配置
+- 共享UI组件包
+
+### Enhancement Details
+
+**What's being added/changed:**
+- 将server从单租户包改为多租户包(如`@d8d/user-module` → `@d8d/user-module-mt`)
+- 租户上下文管理,支持租户ID在请求链中传递
+- 多租户认证中间件,支持租户感知的用户认证
+- web应用全部改为使用多租户UI包(如`@d8d/user-management-ui-mt`)
+- 前端API客户端支持租户上下文传递
+- 租户数据隔离验证和权限控制
+
+**Enhanced architecture:**
+```
+packages/
+├── server/                    # 改为多租户系统
+│   ├── src/
+│   │   └── index.ts (改为多租户包路由)
+├── web/                       # 全部改为多租户UI包
+│   ├── src/
+│   │   ├── client/
+│   │   │   ├── admin/
+│   │   │   │   └── routes.tsx (改为导入多租户UI包)
+│   │   │   ├── api_init.ts (改为初始化多租户客户端)
+│   │   │   └── pages/ (移除本地实现,全部使用包)
+└── 多租户包 (史诗007已完成)
+    ├── @d8d/user-module-mt
+    ├── @d8d/auth-module-mt (已包含租户上下文管理)
+    ├── @d8d/file-module-mt
+    ├── @d8d/user-management-ui-mt
+    ├── @d8d/order-management-ui-mt
+    └── ... (其他多租户UI包)
+```
+
+**How it integrates:**
+- 按照现有server包导入模式,将单租户包替换为多租户包
+- 多租户模块包直接依赖多租户认证模块的认证中间件,其中已包含租户上下文管理
+- 按照web中用户管理UI包的集成模式,将其他管理界面改为使用多租户UI包
+- 保持现有API接口不变,新增租户相关API
+- 前端复用现有UI组件,新增租户管理功能
+- 共享包在两套系统中继续复用
+
+**Success criteria:**
+- server直接使用多租户包,无需环境变量切换
+- 多租户模式下租户数据完全隔离
+- web应用全部使用多租户UI包,移除本地实现
+- 租户管理界面功能完整,支持租户CRUD操作
+- 现有单租户功能不受影响,保持向后兼容
+- 性能影响小于5%,租户过滤使用数据库索引
+- 完整的测试覆盖和文档
+
+## Stories
+
+### 阶段 1: Server多租户集成
+
+1. **Story 1:** Server多租户包替换 - 将server中的单租户包替换为多租户包(如`@d8d/user-module` → `@d8d/user-module-mt`),多租户模块包直接依赖多租户认证模块的认证中间件
+
+2. **Story 2:** 多租户数据实体集成 - 更新数据库实体初始化,使用多租户实体(带_mt后缀),确保租户数据隔离
+
+### 阶段 2: Web多租户UI包集成
+
+3. **Story 3:** Web多租户UI包全面集成 - 按照现有用户管理UI包的集成模式,将web中所有管理界面改为使用多租户UI包(如`@d8d/user-management-ui-mt`),移除本地实现
+
+4. **Story 4:** 前端租户上下文和API客户端增强 - 实现前端的租户上下文管理,增强API客户端支持租户上下文传递,提供租户切换和租户感知的UI组件
+
+### 阶段 3: 系统集成和验证
+
+5. **Story 5:** 多租户系统集成测试和验证 - 进行完整的系统集成测试,验证租户数据隔离、权限控制和性能表现,确保系统稳定性和可靠性
+
+## Compatibility Requirements
+
+- [x] 现有单租户APIs保持不变,多租户为可选功能
+- [x] 数据库schema变更向后兼容,多租户使用独立表
+- [x] 现有UI组件和设计模式保持不变
+- [x] 性能影响最小化,租户过滤使用数据库索引
+- [x] 配置向后兼容,现有配置继续有效
+
+## Risk Mitigation
+
+**Primary Risk:** 租户上下文管理复杂,可能影响现有请求处理
+**Mitigation:** 使用AsyncLocalStorage管理租户上下文,确保线程安全
+**Rollback Plan:** 租户功能为可选配置,可随时禁用回退到单租户模式
+
+**Primary Risk:** 多租户路由切换可能引入路由冲突
+**Mitigation:** 清晰的命名空间分离,单租户和多租户路由独立管理
+**Rollback Plan:** 保持单租户路由不变,多租户路由可独立移除
+
+**Primary Risk:** 前端租户管理界面与现有功能冲突
+**Mitigation:** 租户管理作为独立模块,与现有管理界面分离
+**Rollback Plan:** 租户管理界面可独立禁用,不影响现有功能
+
+**Primary Risk:** 性能影响,租户过滤增加查询复杂度
+**Mitigation:** 数据库索引优化,查询条件合并,性能基准测试
+**Rollback Plan:** 租户过滤可配置禁用,回退到无租户过滤模式
+
+## Definition of Done
+
+- [ ] 所有故事完成且验收标准满足
+- [ ] server支持单租户/多租户模式动态切换
+- [ ] 租户数据隔离验证通过
+- [ ] 租户管理界面功能完整
+- [ ] 现有单租户功能通过回归测试验证
+- [ ] 性能基准测试通过,无明显性能下降
+- [ ] 完整的单元测试和集成测试覆盖
+- [ ] 使用文档和配置说明完整
+- [ ] 向后兼容性验证通过
+
+## 架构设计详情
+
+### Server多租户包集成
+
+```typescript
+// 重构后的server入口 - 直接使用多租户包
+// 当前实际写法(packages/server/src/index.ts:4-6)
+import { userRoutes as userModuleRoutes } from '@d8d/user-module'        // 当前:单租户包
+import { authRoutes as authModuleRoutes } from '@d8d/auth-module'        // 当前:单租户包
+import { fileRoutes as fileModuleRoutes } from '@d8d/file-module'        // 当前:单租户包
+
+// 改为多租户包
+import { userRoutes as userModuleRoutes } from '@d8d/user-module-mt'     // 改为:多租户包
+import { authRoutes as authModuleRoutes } from '@d8d/auth-module-mt'     // 改为:多租户包
+import { fileRoutes as fileModuleRoutes } from '@d8d/file-module-mt'     // 改为:多租户包
+
+// 多租户认证模块包中已实现租户上下文(packages/auth-module-mt/src/middleware/auth.middleware.mt.ts:44-46)
+// 在认证中间件中设置租户上下文:c.set('tenantId', user.tenantId)
+```
+
+### Web多租户UI包集成
+
+```typescript
+// web/src/client/admin/routes.tsx - 改为使用多租户UI包
+import { UserManagement } from '@d8d/user-management-ui-mt'  // 改为多租户UI包
+import { OrderManagement } from '@d8d/order-management-ui-mt'  // 改为多租户UI包
+import { GoodsManagement } from '@d8d/goods-management-ui-mt'  // 改为多租户UI包
+// ... 其他管理界面包
+
+// 路由配置
+{
+  path: 'users',
+  element: <UserManagement />,  // 使用多租户UI包
+},
+{
+  path: 'orders',
+  element: <OrderManagement />,  // 使用多租户UI包
+},
+{
+  path: 'goods',
+  element: <GoodsManagement />,  // 使用多租户UI包
+}
+```
+
+### API客户端初始化
+
+```typescript
+// web/src/client/api_init.ts - 改为初始化多租户客户端
+import { userClientManager } from '@d8d/user-management-ui-mt/api'  // 改为多租户包
+import { orderClientManager } from '@d8d/order-management-ui-mt/api'  // 改为多租户包
+import { goodsClientManager } from '@d8d/goods-management-ui-mt/api'  // 改为多租户包
+
+// 初始化多租户客户端
+userClientManager.init('/api/v1/users')
+orderClientManager.init('/api/v1/orders')
+goodsClientManager.init('/api/v1/goods')
+```
+
+### 前端租户上下文管理
+
+```typescript
+// 租户上下文Hook
+export function useTenant() {
+  const [currentTenant, setCurrentTenant] = useState<Tenant | null>(null);
+
+  const switchTenant = useCallback(async (tenantId: number) => {
+    // 切换租户逻辑
+    const response = await tenantClient.switchTenant({ tenantId });
+    setCurrentTenant(response.data);
+
+    // 更新API客户端租户上下文
+    updateApiClientTenant(tenantId);
+  }, []);
+
+  return {
+    currentTenant,
+    switchTenant,
+    isMultiTenant: !!currentTenant
+  };
+}
+
+// API客户端租户上下文
+export function createApiClient(baseURL: string, tenantId?: number) {
+  const client = rpcClient(baseURL);
+
+  // 添加租户上下文到请求头
+  if (tenantId) {
+    client.$default.headers.set('X-Tenant-ID', tenantId.toString());
+  }
+
+  return client;
+}
+```
+
+### 租户管理界面
+
+```typescript
+// 租户管理页面组件
+export function TenantsPage() {
+  const { data: tenants, isLoading } = useQuery({
+    queryKey: ['tenants'],
+    queryFn: () => tenantClient.index.$get()
+  });
+
+  const createMutation = useMutation({
+    mutationFn: (data: CreateTenantDto) => tenantClient.index.$post({ json: data }),
+    onSuccess: () => {
+      // 刷新租户列表
+      queryClient.invalidateQueries({ queryKey: ['tenants'] });
+    }
+  });
+
+  return (
+    <div className="container mx-auto p-6">
+      <div className="flex justify-between items-center mb-6">
+        <h1 className="text-2xl font-bold">租户管理</h1>
+        <Button onClick={() => setShowCreateDialog(true)}>
+          创建租户
+        </Button>
+      </div>
+
+      <DataTable
+        data={tenants?.data || []}
+        columns={tenantColumns}
+        isLoading={isLoading}
+      />
+
+      <TenantCreateDialog
+        open={showCreateDialog}
+        onOpenChange={setShowCreateDialog}
+        onSubmit={createMutation.mutate}
+      />
+    </div>
+  );
+}
+```
+
+## 实施策略
+
+### 阶段化实施
+1. **第一阶段**: Server多租户集成(多租户包替换、租户上下文、认证增强)
+2. **第二阶段**: Web多租户UI包集成(全面使用多租户UI包、移除本地实现)
+3. **第三阶段**: 系统集成和验证(集成测试、性能测试、文档)
+
+### 数据迁移策略
+- 多租户系统使用全新数据,不迁移现有单租户数据
+- 提供数据导出导入工具
+- 保持两套系统数据独立
+
+## 技术实现要点
+
+### 向后兼容性保证
+1. **包替换**: 直接替换单租户包为多租户包,保持相同API接口
+2. **API 不变**: 现有单租户API接口和行为保持不变
+3. **数据独立**: 多租户使用独立的数据表
+4. **性能隔离**: 两套系统性能互不影响
+
+### 安全性考虑
+1. **租户隔离**: 严格的租户数据隔离机制
+2. **权限控制**: 租户间数据访问权限控制
+3. **输入验证**: 所有用户输入进行严格的验证和转义
+4. **审计日志**: 租户操作审计日志记录
+
+### 性能优化
+1. **数据库索引**: 确保租户ID字段有合适的索引
+2. **查询优化**: 租户过滤条件与现有查询条件合并
+3. **连接池**: 优化数据库连接池配置
+4. **缓存策略**: 租户级缓存策略
+
+## 测试策略
+
+### 单元测试
+- 租户上下文管理测试
+- 多租户包集成测试
+- 认证中间件增强测试
+- 前端租户Hook测试
+
+### 集成测试
+- 租户数据隔离验证测试
+- 租户管理界面功能测试
+- 性能基准测试
+
+### 回归测试
+- 现有单租户功能回归测试
+- 向后兼容性验证测试
+- API接口兼容性测试
+
+---
+
+## Story Manager Handoff
+
+"请为这个brownfield epic开发详细的用户故事。关键考虑因素:
+
+- 这是基于史诗007已完成的多租户包,在现有Node.js + TypeScript + Hono + TypeORM + PostgreSQL + React技术栈上的集成
+- 集成点:现有server包导入模式(packages/server/src/index.ts)、web中用户管理UI包的集成模式
+- 需要遵循的现有模式:server直接包导入、web中UI包集成、Hono中间件、TypeORM实体、React组件、TanStack Query数据获取
+- 关键发现:多租户模块包直接依赖多租户认证模块的认证中间件,其中已实现租户上下文管理(`c.set('tenantId', user.tenantId)`),无需额外添加租户中间件
+- 关键兼容性要求:现有单租户系统完全不变、直接替换为多租户包、性能影响最小化
+- 每个故事必须包含验证现有功能保持完整的回归测试
+
+该epic应按照现有包集成模式,将server和web直接改为多租户系统,为后续按需拼装不同系统提供基础。"
+
+---
+
+**🤖 Generated with [Claude Code](https://claude.ai/code)**
+via [Happy](https://happy.engineering)
+
+**Co-Authored-By: Claude <noreply@anthropic.com>**
+**Co-Authored-By: Happy <yesreply@happy.engineering>**