# 代码库问题

**分析日期:** 2026-02-28

## 技术债务

**租户软删除未实现:**
- 问题: `Tenant` 实体有 `IsDeleted` 属性，但 `TenantStore` 删除操作执行硬删除
- 文件: `Fengling.Platform.Domain/AggregatesModel/TenantAggregate/Tenant.cs`、`Fengling.Platform.Infrastructure/TenantStore.cs`
- 影响: 永久删除租户，破坏引用完整性和审计跟踪
- 修复方法: 在 `TenantStore.DeleteAsync()` 中实现软删除并添加全局查询过滤器

**ApplicationUser 软删除未强制:**
- 问题: `ApplicationUser.IsDeleted` 属性存在，但没有 EF Core 全局查询过滤器强制执行
- 文件: `Fengling.Platform.Domain/AggregatesModel/UserAggregate/ApplicationUser.cs`、`Fengling.Platform.Infrastructure/PlatformDbContext.cs`
- 影响: 已删除用户仍可被查询和认证
- 修复方法: 在 `PlatformDbContext.OnModelCreating` 中为 `ApplicationUser` 添加 `HasQueryFilter`

**混合 DateTime 使用:**
- 问题: `Tenant` 使用 `DateTime`，而 `ApplicationUser`/`ApplicationRole` 使用 `DateTimeOffset`
- 文件: `Fengling.Platform.Domain/AggregatesModel/TenantAggregate/Tenant.cs`、`Fengling.Platform.Domain/AggregatesModel/UserAggregate/ApplicationUser.cs`、`Fengling.Platform.Domain/AggregatesModel/RoleAggregate/ApplicationRole.cs`
- 影响: 实体间时区不一致，可能出现 UTC/混合时区 bug
- 修复方法: 将所有时间属性统一为 `DateTimeOffset`

**重复的 TenantId 数据类型:**
- 问题: `AccessLog.TenantId` 和 `AuditLog.TenantId` 是 `string?`，而 `Tenant.Id` 是 `long`
- 文件: `Fengling.Platform.Domain/AggregatesModel/UserAggregate/AccessLog.cs`、`Fengling.Platform.Domain/AggregatesModel/UserAggregate/AuditLog.cs`
- 影响: 类型不匹配，可能数据损坏，查询问题
- 修复方法: 改为 `long?` 以匹配 `Tenant.Id` 类型

**未配置 RowVersion 用于乐观并发:**
- 问题: `Tenant.RowVersion` 属性存在，但没有 EF Core 并发令牌配置
- 文件: `Fengling.Platform.Domain/AggregatesModel/TenantAggregate/Tenant.cs`、`Fengling.Platform.Infrastructure/Configurations/TenantConfiguration.cs`
- 影响: 乐观并发更新可能在未检测的情况下覆盖更改
- 修复方法: 在配置中为 `RowVersion` 属性添加 `.IsRowVersion()`

---

## 已知 Bug

**租户 Store 泛型约束问题:**
- 问题: `TenantStore<TContext>` 需要泛型参数，但 `ITenantStore` 接口是非泛型的，使 DI 注册变得笨拙
- 文件: `Fengling.Platform.Infrastructure/TenantStore.cs`、`Fengling.Platform.Infrastructure/ITenantStore.cs`
- 触发: 注册 `TenantStore<PlatformDbContext>` vs `ITenantStore`
- 变通方案: 使用工厂模式或开放泛型注册

**ApplicationUser 导航属性缺失:**
- 问题: `ApplicationUser` 没有到 `Tenant` 的导航属性，强制通过 `TenantInfo` 进行连接
- 文件: `Fengling.Platform.Domain/AggregatesModel/UserAggregate/ApplicationUser.cs`
- 影响: 无法在用户查询中轻松预加载租户数据
- 修复方法: 添加 `public Tenant? Tenant { get; set; }` 并正确配置

---

## 安全考虑

**默认查询中无租户隔离:**
- 风险: `TenantStore.GetAllAsync()` 返回所有租户，无授权检查
- 文件: `Fengling.Platform.Infrastructure/TenantStore.cs`
- 当前缓解: 无
- 建议: 在所有列表操作中添加授权检查或实现租户范围查询

**角色权限序列化:**
- 风险: `ApplicationRole.Permissions` 是 `List<string>?` - 无加密或验证
- 文件: `Fengling.Platform.Domain/AggregatesModel/RoleAggregate/ApplicationRole.cs`
- 当前缓解: 无
- 建议: 考虑带验证的结构化权限模型

**访问/审计日志敏感数据:**
- 风险: `AccessLog` 将 `RequestData` 和 `ResponseData` 存储为纯字符串，可能包含 PII/密钥
- 文件: `Fengling.Platform.Domain/AggregatesModel/UserAggregate/AccessLog.cs`
- 当前缓解: 无
- 建议: 实现数据脱敏或从日志中排除敏感字段

---

## 性能瓶颈

**租户查找无缓存:**
- 问题: 每次租户检查都查询数据库 - `FindByIdAsync`、`FindByTenantCodeAsync`
- 文件: `Fengling.Platform.Infrastructure/TenantStore.cs`
- 原因: 无分布式或内存缓存
- 改进路径: 为租户查找添加 `IMemoryCache` 或分布式缓存

**GetAllAsync 加载整表:**
- 问题: `TenantStore.GetAllAsync()` 将所有租户加载到内存中使用 `ToListAsync()`
- 文件: `Fengling.Platform.Infrastructure/TenantStore.cs`（第 34 行）
- 原因: `GetAllAsync` 无分页支持
- 改进路径: 始终使用分页查询；弃用 `GetAllAsync`

**重复查询逻辑:**
- 问题: 过滤逻辑在 `GetPagedAsync` 和 `GetCountAsync` 中重复
- 文件: `Fengling.Platform.Infrastructure/TenantStore.cs`（第 40-72 行）
- 原因: 无查询构建器抽象
- 改进路径: 提取到共享谓词构建器

---

## 脆弱区域

**租户 Store 删除级联:**
- 文件: `Fengling.Platform.Infrastructure/TenantStore.cs`（第 90-95 行）
- 为何脆弱: 硬删除不检查相关用户/角色 - 可能使数据孤立
- 安全修改: 删除前添加引用完整性检查
- 测试覆盖: 未找到级联删除场景的测试

**TenantCode 更改无验证:**
- 文件: `Fengling.Platform.Infrastructure/TenantStore.cs`（第 135-139 行）、`TenantManager.cs`（第 70-74 行）
- 为何脆弱: `SetTenantCodeAsync` 在更新前不检查唯一性
- 安全修改: 持久化前添加唯一性验证
- 测试覆盖: 未找到重复代码场景的测试

**通用 Store 模式不完整:**
- 文件: `Fengling.Platform.Infrastructure/TenantStore.cs`
- 为何脆弱: `TenantStore<TContext>` 实现 `ITenantStore` 但无基类 - 复制了 ASP.NET Identity 的模式
- 安全修改: 考虑继承 `TenantStoreBase` 或正确添加接口实现
- 测试覆盖: 未找到单元测试

---

## 扩展限制

**数据库:**
- 当前容量: 通过 EF Core 的单个 PostgreSQL 实例
- 限制: 无只读副本配置，仅垂直扩展
- 扩展路径: 实现读写分离，添加连接池调优

**日志:**
- 当前容量: 访问/审计日志写入与实体相同的数据库
- 限制: 高容量日志会降低事务性能
- 扩展路径: 实现带后台队列的异步日志，考虑单独日志存储

---

## 有风险的依赖

**NetCorePal.Extensions 包:**
- 风险: 来自 `NetCorePal` 命名空间的自定义/内部包
- 影响: 版本兼容性问题，可能破坏性变更
- 迁移计划: 监控包发布，维护版本锁定

**OpenIddict.EntityFrameworkCore:**
- 风险: 复杂配置的 OpenID 提供程序
- 影响: 数据库模式变更需要迁移
- 迁移计划: 保持迁移更新，升级时审查破坏性变更

**net10.0 目标:**
- 风险: .NET 10 是未来版本（当前: .NET 8/9）
- 影响: 稳定性和 LTS 担忧
- 迁移计划: 目标稳定 LTS（.NET 8）直到 .NET 10 发布

---

## 缺失的关键功能

**无租户过滤中间件:**
- 问题: 无中间件从请求中提取租户并强制隔离
- 阻塞: API 级别的多租户数据隔离

**无租户订阅/配额强制:**
- 问题: 配置了 `MaxUsers` 但在用户创建时从不检查
- 阻塞: 防止租户超出用户限制

**无租户变更审计跟踪:**
- 问题: 创建/更新/删除租户时无自动日志记录
- 阻塞: 合规性和变更跟踪

**无用户邀请系统:**
- 问题: 多租户用户入驻无邀请流程
- 阻塞: 受控用户注册

---

## 测试覆盖缺口

**未找到单元测试:**
- 未测试: 所有核心功能
- 文件: 解决方案中未检测到测试项目
- 风险: 租户管理、认证和授权中的 bug 未被检测
- 优先级: **高**

**租户 CRUD 操作:**
- 未测试: 租户的创建、读取、更新、删除
- 文件: `Fengling.Platform.Infrastructure/TenantManager.cs`、`TenantStore.cs`
- 风险: 业务逻辑 bug 隐藏
- 优先级: **高**

**多租户隔离:**
- 未测试: 跨租户数据访问预防
- 文件: 所有查询操作
- 风险: 租户数据泄露导致安全漏洞
- 优先级: **关键**

---

*问题审计: 2026-02-28*
