MasterData 的 GA 不等于“九张表能建出来”。它必须证明资产可信、跨 ORM 等价、重复导入安全、读缓存一致、租户隔离、管理变更可审计且可回滚。
1. 当前成熟度
| 维度 | 当前证据 | 主要缺口 |
|---|---|---|
| 所有权 | 架构测试守住 owner-local 与旧路径删除 | 独立包边界仍与 I18n Infrastructure 耦合 |
| 元数据 | 九种编译期模型门禁 | 业务约束并不完整 |
| ORM | IEntitySet 与 parity 测试基础 | 全目录/大数据行为需证明 |
| 种子 | 八步骤、端到端 seed 测试 | 严格 schema、diff、最小行数、bulk/事务 |
| 读取 | Resolver、租户 cache key、回退 | 复合键碰撞、精确失效、culture fallback |
| 治理 | Feature 与两个 read permissions | 无 Endpoint/管理权限/实际强制 |
| 运维 | 日志记录 upsert count | SLO、dashboard、告警、runbook、回滚报告 |
2. 当前测试证据
MasterDataInfrastructureArchitectureTests 覆盖:
- Framework 旧行、SqlSugar seed、CSV 和 EF 手写配置保持删除;
- 九个 CatalogRecord、八个资产存在;
- Infrastructure 不引用具体 ORM;
- 八个步骤继承 EntitySet CSV 基类;
- API Host 引用并注册 Resolver;
- Resolver 依赖 owner-local IEntitySet;
- 九个类型有正确表名、tenant、soft-delete 生成元数据。
Integration Tests 还把这些记录加入持久化元数据、repository parity 与 seed 端到端场景。
3. 尚未被证明的事实
现有测试没有证明四个空资产可用、43k 数据性能、Code/Class 本地化碰撞、生产缓存传播、授权入口或数据权威性。
4. 数据质量契约
每个目录应有独立 contract:
| 检查 | 示例 |
|---|---|
| schema | exact header、类型、required |
| identity | unique key 与 index/Match 对齐 |
| cardinality | 最小/最大行数、突变阈值 |
| referential | ParentCode 存在、树无环 |
| semantic | BCP-47、ISO code、币种、日期范围 |
| governance | authority、revision、license、owner |
| compatibility | 已发布 code 不被无计划删除/改义 |
报告应作为 CI 制品和发布证据保存。
5. 属性测试示例
// ① 所有行必须以数据库与 Resolver 共识的复合键唯一。var rows = seedReader.Read<SysGeneralCodeCatalogRecord>(assetRequest);rows.GroupBy(row => new { row.TenantId, row.Group, row.Class, row.Code }) .Where(group => group.Count() > 1) .ShouldBeEmpty();
// ② 每个非空父级都必须存在,且沿父链不能回到自身。var byCode = rows.ToDictionary(row => (row.Class, row.Code));foreach (var row in rows.Where(row => row.ParentCode is not null)) CatalogGraph.AssertAcyclicAndParentExists(row, byCode);应按真实领域身份调整键;示例说明门禁形态,不代表当前已实现。
6. 双 ORM 验证矩阵
每个支持的 adapter 都要跑:
- 空库 schema 初始化与生成元数据;
- 首次 seed 的 inserted/updated/failed 报告;
- 完全相同资产第二次执行,数据与审计稳定;
- 一个显示字段变化,只更新目标行;
- key 冲突、类型错误、取消和中途故障;
- tenant=0 与普通 tenant 查询隔离;
- Resolver 的 Contains、排序和软删行为;
- 大资产冷/热运行耗时和 SQL 往返。
只比较最终行数不足以发现错误覆盖。
7. 生产启动与就绪
种子执行应和 API readiness 明确协调:
如部署采用独立 migration/seed job,API readiness 应检查期望 catalog revision,而不是自行并发执行同一大资产。
8. 指标与告警
建议指标:
master_data_seed_duration:seed_id、outcome;master_data_seed_rows:inserted/updated/unchanged/failed;master_data_asset_revision_info:低基数 revision;master_data_dictionary_cache:hit/miss/negative;master_data_dictionary_resolve:hit/raw-code/error;master_data_invalidation_lag:catalog revision 延迟;master_data_data_quality_failures:contract/check。
不要用 group/code/tenant 作高基数指标标签。
9. 审计与变更管理
当前没有 MasterData 写入 API。未来管理面至少需要:草稿、diff、审批、计划发布时间、发布版本、变更原因、影响扫描、回滚版本、操作者与审计证据。
IsProtect 目前只是字段;管理 handler 必须真正阻止普通用户变更。Feature 只决定可用性,管理应有独立 create/update/publish 权限,而不是复用 read。
10. 备份与回滚
- 发布前备份受影响 tenant/catalog;
- 保存资产 digest 与 before/after diff;
- 回滚以新修订重新应用,不手工改生产表;
- 已被业务引用的新 code 不能简单删除;
- 缓存失效与回滚同一流程;
- Translation/I18n 影响要一起评估;
- 大批失败后可从批次 checkpoint 恢复。
11. 商业 GA 阶段
| Gate | 必须完成 |
|---|---|
| G0 身份 | 九目录的 owner、自然键、scope、authority、version 定义 |
| G1 资产 | 严格 schema、内容质量、diff、digest、许可证门禁 |
| G2 持久化 | unique/Match/resolver 对齐、双 ORM 等价、迁移兼容 |
| G3 读取 | 复合键、culture fallback、精确跨实例失效、版本可观测 |
| G4 管理 | Application/API、Feature/Permission、审批、审计、回滚 |
| G5 性能 | 43k+ 冷启动、批量 upsert、事务/恢复达到 SLO |
| G6 运维 | readiness、指标、告警、dashboard、runbook、演练 |
任何核心目录只有表头或权威版本不可验证时,不能宣称该目录 GA。
12. 发布判定示例
// ① 所有启用目录都必须提供同一 revision 的验证和运行证据。var evidence = await gaEvidence.LoadAsync(release.Revision, cancellationToken);foreach (var catalog in release.EnabledCatalogs){ evidence.RequirePassed(catalog, "schema"); evidence.RequirePassed(catalog, "dual-orm-repeat-seed"); evidence.RequirePassed(catalog, "tenant-isolation"); evidence.RequirePassed(catalog, "rollback-drill");}
// ② 只要存在 header-only 核心资产或 warning,发布门禁失败。if (evidence.HasWarnings || evidence.AnyRequiredCatalogIsEmpty) throw new CommercialGaGateException(evidence.Summary);13. 当前优先级
最高优先级不是先做 UI,而是:
- 修复 CodeText 复合身份与汇率字段漂移;
- 建严格资产 validator,把 warning 提升为门禁;
- 明确空资产是可选还是必须补齐;
- 建 43k 行双 ORM 性能/恢复基线;
- 修正字典精确失效和 culture 语义;
- 再建设带审批/审计的管理面。
14. 执行命令
dotnet test tests/BitzOrcas.Architecture.Tests/BitzOrcas.Architecture.Tests.csproj --no-restore --filter MasterDataInfrastructureArchitectureTestsdotnet test tests/BitzOrcas.Integration.Tests/BitzOrcas.Integration.Tests.csproj --no-restore --filter "Seed|MasterData"
# 暴露旧路径与 ORM 泄漏;预期无命中。rg -n "SysCountryEntity|SqlSugarDataDictionaryResolver|MasterDataEntityConfigurations" src -g '*.cs'