# 代码库问题 **分析日期:** 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` 需要泛型参数,但 `ITenantStore` 接口是非泛型的,使 DI 注册变得笨拙 - 文件: `Fengling.Platform.Infrastructure/TenantStore.cs`、`Fengling.Platform.Infrastructure/ITenantStore.cs` - 触发: 注册 `TenantStore` 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?` - 无加密或验证 - 文件: `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` 实现 `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*