8.5 KiB
Java 单租户多客户设计审计计划
状态说明:本文保留第一轮只读审计的原始计划。用户随后明确授权修改代码、初始化 SQL 与测试环境数据;实际执行结果以同日《Java 单租户多客户设计审计汇总结论》和统一增量 SQL 为准。
一、目标
对 baiyue-firstleg/ 全部 Java 服务、数据库脚本和跨服务契约做一次系统性只读审计,确认当前实现符合根 AGENTS.md 已确定的阶段模型:
- 当前业务单租户,平台管理多个客户,客户之间严格隔离。
iam_tenant中id > 0 && tenant_type = MERCHANT的记录当前直接作为客户主档。- Auth、JWT 和业务表中的
tenant_id > 0当前承载客户 ID,是客户隔离键。 tenant_id = 0是平台或 RBAC 模板技术作用域,不是未来的默认租户。- 平台公共仓库、往来单位、快递公司、托盘、库位等公共资源归属平台技术作用域
tenant_id = 0;客户订单、文件和费用等私有数据仍使用客户 ID。 - 当前不新增真实租户层,不重命名现有兼容字段,不做大规模架构改造。
审计完成后,主对话统一汇总结论,再以最小改造原则安排修改。第一轮各审计对话一律只读,不修改任何文件。
二、非目标
- 不在本轮设计或实现真实多租户。
- 不把现有
tenant_id统一替换为默认租户 ID。 - 不批量重命名
tenant、merchant、Tenant*、tenant_id。 - 不因为未来可能支持多租户而提前增加租户表、租户切换、租户级 RBAC 或租户级配置。
- 第一轮审计阶段不修改测试环境数据;后续已按用户在当前对话中的明确授权执行统一迁移。
三、统一审计判定标准
每个业务入口和数据链路都按以下问题检查:
- 平台账号是否固定为
app_code = PLATFORM && tenant_id = 0。 - 客户账号是否固定为
app_code = MERCHANT && tenant_id > 0,成员关系是否属于同一客户。 - 商户端是否只从可信认证上下文取得当前客户 ID,而不是信任请求中的目标
tenantId。 - 平台端跨客户查询或代客操作是否同时校验平台应用域、权限码和目标客户条件。
- Repository、Mapper、SQL 是否在客户数据的查询、更新、删除和唯一约束中携带当前客户 ID。
- 子表、历史、审计、Outbox、幂等、文件和缓存键是否继承主聚合的客户 ID。
- 内部 API、Feign DTO 和事件是否完整传递客户 ID,并在被调用方再次按归属校验。
tenant_id = 0是否只用于平台或全局模板,是否被错误当成客户或未来默认租户。customer_id、data_scope_id、operator_tenant_id、public-tenant-id等相邻字段是否被误用为 IAM 客户隔离键。- 是否存在通用路由、可选过滤、按主键裸查、跨库查询或平台/商户端域混用造成的跨客户访问风险。
- 当前实现是否偷偷引入真实租户层,或制造一年后无法通过新增上级租户字段迁移的不可逆结构。
- 自动化测试是否至少覆盖客户 A 不能读取或修改客户 B 数据,以及平台合法跨客户操作。
四、第一轮多对话分工(全部只读)
对话 A:IAM、Auth、Common Security、Gateway
负责目录:iam/、auth/、common-security/、gateway/。
重点检查账号归属、注册、成员、角色权限模板、授权快照、JWT Claim、刷新撤销、可信身份头、平台/商户访问域和 Gateway 路由。确认平台 0、客户 >0 的规则在所有入口一致,检查历史账号脏数据风险及通用路由绕过。
对话 B:Order 客户隔离
负责目录:order/。
重点检查商户下单、平台代客、列表详情、状态流转、货物/参与方/历史/备注、幂等、Outbox、IAM 资格查询和 Warehouse 主数据调用。必须区分当前隔离键 tenant_id 与往来单位语义的 customer_id。
对话 C:Firstleg 履约与二期入库
负责目录:firstleg/。
重点检查履约任务、入库单、测量、审核、FBA 计费、费用发布、托盘库位协作、第三方测量、内部接口、幂等和 Outbox。核对所有状态推进、详情和图片链路是否使用同一个客户 ID。
对话 D:Warehouse 与 File 资源归属
负责目录:warehouse/、file/。
重点检查仓库、往来单位、快递公司、托盘、库位、预占占用、资质文件、测量图片和导出任务。单独核对 DEFAULT_TENANT_ID / public-tenant-id 是否固定为平台作用域 0,确保公共仓库、往来单位和快递公司等资源不再绑定普通客户 10001;客户文件仍按客户隔离。
对话 E:其余服务与公共契约
负责目录:common-core/、common-web/、common-audit/、common-event-contract/、common-openapi/、audit-service/、integration-service/、event-bridge-service/、print/。
重点检查公共实体、审计上下文、事件信封、内部令牌、OpenAPI 自动配置、第三方适配和打印下载链路是否丢失、混淆或信任外部提交的客户 ID。
对话 F:数据库、迁移与部署配置
只负责各模块 src/main/resources/db/、deploy/sql/、deploy/、config/nacos/、相关初始化脚本,不审计 Java 业务实现。
重点检查表、索引、唯一键、增量迁移、种子数据和环境配置中的客户隔离维度;盘点 tenant_id = 0、10001 等保留值的真实用途;提出上线前只读数据核验 SQL,不执行写操作。
对话 G:测试、OpenAPI、文档与三期防返工
只负责 src/test/、各模块 src/main/resources/openapi/、docs/ 和模块 README / AGENTS.md,不修改生产代码。
检查测试是否覆盖跨客户拒绝、平台跨客户、内部调用归属和端域隔离;检查契约及文档是否仍把当前 tenant_id 描述成真实上级租户;定向核对三期文档,列出可能诱导后续按三级租户开发的内容。
五、每个审计对话的统一输出格式
每项发现必须包含:
- 编号和风险级别。
- 结论:符合、缺口或需要业务确认。
- 可复核证据:绝对文件路径和准确行号。
- 触发场景及可能造成的跨客户或上线影响。
- 最小修复建议,明确涉及的文件和消费者。
- 建议增加或调整的测试。
- 是否应延后到约一年后的真实租户迭代。
风险级别统一为:
P0:可直接造成未授权跨客户读写、身份伪造或生产数据破坏,阻断上线。P1:明确的隔离缺口、端域绕过或高概率配置错误,应在上线前修复。P2:防御性加固、测试缺口、易误用设计或运维核验项,可在上线前排期完成。Deferred:只与未来真实多租户有关,当前禁止提前改造,仅记录迁移边界。
没有发现问题的负责范围也必须给出检查过的入口、隔离链路和测试证据,不能只回复“未发现问题”。
六、汇总与裁决流程
- 主对话等待全部只读审计完成,去重并处理跨模块结论冲突。
- 以当前根
AGENTS.md为事实来源,把发现分成“必须上线前修改、上线前建议加固、仅需数据核验、延后到真实租户阶段”。 - 对跨模块字段和契约,由主对话确定唯一兼容策略;任何审计对话不得自行决定重定义
tenant_id。 - 输出修改清单、文件所有权、依赖顺序、验证命令和回滚边界,用户确认后进入修改阶段。
七、第二轮修改对话安排原则
- 修改对话数量由最终发现决定,不预先假设每个审计对话都有代码要改。
- 每个修改对话拥有互斥的生产文件范围;公共 DTO、事件、OpenAPI 和统一 SQL 入口由主对话协调。
- 优先处理 P0/P1,再处理测试和文档;
Deferred项不得实现。 - 每个修改对话只运行目标模块实际声明的测试;主对话最后执行受影响模块及跨模块消费者验证。
- 所有修改完成后再次定向检索
tenant_id、customer_id、operator_tenant_id、DEFAULT_TENANT_ID和通用/api/iam/**路由,确认没有新增语义漂移。
八、最终交付物
- 全仓单租户多客户设计审计结论。
- 按优先级排序的最小修改清单及完成状态。
- 上线前只读数据核验 SQL 和配置核对清单。
- 受影响模块测试与跨服务契约验证结果。
- 更新后的根/模块
AGENTS.md、必要 OpenAPI 和回归记录。 - 约一年后引入真实租户时必须保留的迁移边界清单。