# 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. **[x] Story 1:** Server多租户包替换和集成 - 在server的index.ts文件中，将单租户包替换为多租户包（如`@d8d/user-module` → `@d8d/user-module-mt`），包括包导入、实体初始化和路由注册，多租户模块包直接依赖多租户认证模块的认证中间件

2. **[x] Story 2:** Web多租户UI包全面集成 - 按照现有用户管理UI包的集成模式，将web中所有管理界面改为使用多租户UI包（如`@d8d/user-management-ui-mt`），移除本地实现

### 阶段 2: 租户模块和UI包集成

3. **[x] Story 3:** 租户模块集成到server - 将租户模块包（@d8d/tenant-module-mt）集成到server中，包括租户管理路由、超级管理员认证和租户数据隔离功能，确保server能够支持租户管理操作

4. **[x] Story 4:** 租户UI包集成到Web - 复制`web/src/client/admin`目录为`web/src/client/tenant`，在tenant目录中集成`@d8d/tenant-management-ui-mt`租户管理UI包，使用超级管理员认证系统（superadmin/admin123），添加租户管理路由和超级管理员认证逻辑，确保Web应用能够支持租户管理操作

### 阶段 3: 系统集成和验证

5. **[x] 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

- [ ] 所有故事完成且验收标准满足 (4/5 故事已完成)
- [ ] 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包
}
```

### 租户UI包集成实施步骤

```bash
# 1. 复制admin目录为tenant目录
cp -r web/src/client/admin web/src/client/tenant

# 2. 修改tenant目录中的关键文件
# - web/src/client/tenant/index.tsx: 替换AuthProvider为租户专用的AuthProvider
# - web/src/client/tenant/hooks/AuthProvider.tsx: 实现租户感知的认证逻辑
# - web/src/client/tenant/pages/Login.tsx: 添加租户选择功能
# - web/src/client/tenant/routes.tsx: 添加租户管理路由

# 3. 集成租户管理UI包
# - 在routes.tsx中添加租户管理路由
# - 在api_init.ts中初始化租户管理客户端
```

```typescript
// web/src/client/tenant/routes.tsx - 添加租户管理路由
import { TenantsPage } from '@d8d/tenant-management-ui-mt';

// 在路由配置中添加
{
  path: 'tenants',
  element: <TenantsPage />,  // 租户管理界面
},

// web/src/client/tenant/api_init.ts - 初始化租户管理客户端
import { tenantClientManager } from '@d8d/tenant-management-ui-mt/api';

// 初始化租户管理客户端
tenantClientManager.init('/api/v1/tenants');

// web/src/client/tenant/hooks/AuthProvider.tsx - 使用超级管理员认证
const handleLogin = async (username: string, password: string): Promise<void> => {
  // 使用租户模块的超级管理员登录API
  const response = await tenantClientManager.get().login.$post({
    json: {
      username,
      password
    }
  });
  // ... 其他登录逻辑
};

// web/src/client/tenant/pages/Login.tsx - 超级管理员登录页
// 使用固定的超级管理员账号进行登录，无需租户选择
```

### 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)`），无需额外添加租户中间件
- 故事结构简化：Server多租户集成（包替换、实体初始化、路由注册）在同一个文件中完成，前端无需租户上下文管理
- 关键兼容性要求：现有单租户系统完全不变、直接替换为多租户包、性能影响最小化
- 每个故事必须包含验证现有功能保持完整的回归测试

该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>**