# Meta Schema 用量投影建模 —— 评审版设计 > 版本:v0.2(评审版) · 日期:2026-06-17(决策确认 2026-06-20) · 目标读者:架构决策者(人类) · 类型:评审版(结论先行,无代码细节) > 状态:**待决策提案、非现行设计**。方向已确认(2026-06-20,见 §十),但 ⚠️ **本评审版的方案前提已被执行版证伪**——见 [执行版 v0.2](2026-06-20-meta-schema用量投影-execution.md) 顶部「评审修订摘要」(破坏字段集生产者 + schema_key 来源在代码中**不存在、须从零新建**)。落地细节与修正以执行版为准;本文件不实现任何代码。 > 关联:[进度总账 §五A](../mvp/进度总账.md)(MetaImpactFacade 置后判定)、[bc-boundaries](../../.agents/rules/bc-boundaries.md)(本设计须遵守的边界门)。 --- ## 一、结论先行 1. **问题本质**:Meta 治理写链路(publish/activate/rollback/deprecate 4 端点)在 service 层**硬性前置**一条 `status=succeeded` 的 impact preview;而唯一实现 `UnavailableMetaImpactFacade` 恒抛 `META_EXTERNAL_OWNER_UNAVAILABLE`,故这 4 端点**运行期 100% 阻断**。这是**诚实 fail-closed**(拒绝伪造 impact 数量),非缺陷。 2. **根因**:impact preview 要回答"改这个 schema 版本影响哪些消费方实例、几个命中破坏性改动";但消费方**没持久化"谁在用哪个 schema"**——Content 的 `muse_content_planning_section` 仅存 `schema_version`(整数版本号、**无 `schema_key`**),Knowledge/AI **完全不存** schema 引用。**无数据可计数 → facade 只能 fail-closed**。 3. **推荐方向(待确认)**:**Pull(按需查询)+ 按 BC 拆分贡献者端口**,分阶段按消费 BC 落地。即: - 消费方在写入实例时持久化其 schema 用量(至少 `schema_key + version`,Content 已有 version、补 key); - Meta 定义 `MetaSchemaUsageContributorApi`(meta-api),**各消费 BC 实现自己维度的查询**(本域查本域 DAL),Meta 侧聚合器实现 `MetaImpactFacade` 扇出汇总; - 现有 `MetaSchemaImpactPreviewServiceImpl` 调用方**不变**。 4. **关键架构订正**:现有 `MetaImpactFacade` 单接口返回全部 5 维度(Work/Planning/Knowledge/AI/Export),**隐含单一实现者要懂 5 个 BC 的数据 → 违反 BC 边界门**(`no_business_bc_may_depend_on_another_bc_*`)。本设计**必须**把它拆为"Meta 定义端口、各 owner BC 提供适配器"(与刚落地的 `MarketAccountProjectionFacade`/`MuseAccountRecordProjectionApi` 同范式)。 5. **为何不选 Push(事件投影)**:见 §五权衡。一句话:impact preview 是**低频 admin 操作 + 闸destructive 治理动作**,要求**准确**(不能用滞后的投影门destructive 操作),Pull 无投影漂移/无回填/无最终一致性窗口,且匹配现有同步 facade 契约;Push 的投影表+消费 worker+回填+一致性窗口在此场景是净负担。 --- ## 二、背景(事实基线,均有代码出处) > 详细出处见 grounding 调查(本次会话,只读)。下列为硬事实。 - **端口**:`MetaImpactFacade.previewMetaSchemaDraftImpact(schemaKey, draftVersion, draftHash)` → `MetaSchemaImpactSummary{workImpact, planningImpact, knowledgeProjectionImpact, aiContextImpact, exportImpact, totalAffectedProjectionCount}`,位于 `meta.application.facade`。唯一实现 `UnavailableMetaImpactFacade` 抛 `META_EXTERNAL_OWNER_UNAVAILABLE(1_042_001_004)`。 - **硬门禁**:`MetaSchemaServiceImpl` 的 publish/activate/rollback/deprecate 均前置 `requireImpactPreview`(需 `status=succeeded` 的 `muse_meta_impact_preview` 记录,否则 `META_IMPACT_PREVIEW_REQUIRED 1_042_001_002`)。 - **impact 语义**:每个消费维度的**定量快照**——受影响实例数 + 命中破坏性改动(字段移除/可见性改变/投影需重建)的实例数。 - **消费方持久化现状(根因)**:Content `muse_content_planning_section.schema_version`(INT,无 `schema_key` 列、无用量表);Knowledge/AI **无任何** schema 引用持久化。 - **已有数据模型**:`muse_meta_impact_preview`(JSONB 存 impact_summary/error/source_snapshot + status,**一次性预览快照、非累计用量**);无任何 usage/projection 累计表;无独立 usage/export 模块。 - **可复用事件基建**:Content 有成熟幂等 outbox(`ContentEventPublishOutboxServiceImpl`:insertIgnore + worker claim + 重试);AI/Knowledge 有 outbox 接口;`EventsPublishApi` 跨 BC 事件。 --- ## 三、目标 / 非目标 **目标** - 让 4 个 Meta 治理端点从"恒 fail-closed"变为"基于**真实**消费用量给出 impact preview 后可放行",且**绝不伪造** impact 数量。 - 真实化路径**遵守 BC 边界门**(Meta 不直连他域 DAL / application)。 - 可分阶段交付:每阶段一个消费维度真实化,未真实化维度保持**诚实 fail-closed 或显式 0/unknown**(不伪造)。 **非目标(本轮)** - 不做实时/全量用量大盘或运营报表。 - 不引入独立 `muse-module-usage`/`export` 模块(除非评审认定必要)。 - 不改 `MetaSchemaImpactPreviewServiceImpl` 的对外语义与现有 4 端点的 API 契约。 - 不在前端做 admin 可视化(meta 治理属 admin 侧、用户价值低,排后)。 --- ## 四、推荐方案(Pull + 按 BC 拆分贡献者端口) ### 4.1 架构总览 ```mermaid flowchart TD A[AdminMetaSchemaController\npublish/activate/rollback/deprecate] --> B[MetaSchemaServiceImpl.requireImpactPreview] B --> C[MetaSchemaImpactPreviewServiceImpl] C --> D[MetaImpactFacade 聚合器实现\nmeta-server] D -->|fan-out 查询| E1[Content 贡献者适配器\ncontent-server 查本域 DAL] D -->|fan-out 查询| E2[Knowledge 贡献者适配器\nknowledge-server] D -->|fan-out 查询| E3[AI 贡献者适配器\nai-server] D -->|聚合| F[MetaSchemaImpactSummary] F --> G[(muse_meta_impact_preview\n仍存快照)] subgraph 端口契约 meta-api P[MetaSchemaUsageContributorApi\nMeta 定义、各 owner BC 实现] end E1 -. implements .-> P E2 -. implements .-> P E3 -. implements .-> P D -. 依赖 .-> P ``` ### 4.2 两层改造 - **基础层(各消费 BC,特征工程)**:在实例写入时持久化其 schema 用量,使"哪些实例用了 schemaKey X 的哪些字段"可被**本域查询**。Content 已有 `schema_version`,补 `schema_key`(+必要时字段使用快照);Knowledge/AI 视其是否真消费 schema 决定是否纳入(见 open item 1)。 - **端口层(契约)**:meta-api 定义 `MetaSchemaUsageContributorApi`(本进程内 Bean 端口,参照 `MuseContentWorkOwnerApi` 先例,非 @FeignClient);各 owner BC 在 `*-server` 实现自己维度的计数/破坏性分析(只读本域 DAL);meta-server 的 `MetaImpactFacade` 真实聚合器扇出各贡献者、组装 `MetaSchemaImpactSummary`。 ### 4.3 分阶段(价值/可验证性优先) | 阶段 | 内容 | 完成后效果 | |---|---|---| | P0 | meta-api 定义贡献者端口 + meta-server 聚合器(未接消费方时对各维度**显式 unknown/fail-closed**,绝不 0 伪装) | 端口就位,行为等价现状但架构可扩展 | | P1 | Content(work + planning)真实化:补 `schema_key` 持久化 + Content 实现贡献者适配器 | Content 维度真实计数,治理端点对"仅 Content 受影响"可放行 | | P2+ | Knowledge / AI / Export 逐维度真实化(各自 owner 出适配器) | 其余维度逐步真实 | > 每阶段验收=该维度真实 PG IT(种真实消费实例→preview 返回真实计数;负路径未接入维度 fail-closed 不伪造)。 --- ## 五、关键权衡:Pull vs Push | 维度 | Pull(推荐:按需查询贡献者) | Push(事件投影:消费方发用量事件→Meta 投影表) | |---|---|---| | 准确性 | **实时准确**,直接查源 | 最终一致,有滞后窗口——**用滞后投影 gate destructive 治理动作有风险** | | 新增数据模型 | 无新累计表(复用 impact_preview 快照) | 需 `muse_meta_schema_usage_projection` + 消费 worker | | 历史数据 | 无需回填(直接扫源) | **需回填**既有实例,否则投影不全 | | BC 边界 | 各 BC 查本域(合规) | 各 BC 发事件 + Meta 消费(合规),但组件更多 | | 成本/复杂度 | 低(匹配现有同步 facade 契约) | 高(发布点+outbox+worker+回填+一致性) | | 频率匹配 | impact preview 低频 admin,扫描成本可接受 | 投影适合高频读;此场景高频读不存在 | | 共同前提 | **两者都需消费方持久化 schema 用量**(根因不可绕过) | 同 | **结论**:在"低频、要准确、gate destructive 操作"的 impact preview 场景,Pull 显著优。Push 的优势(高频读、解耦)在此不构成价值,反引入投影漂移与回填负担。**故推荐 Pull**。(若未来出现"运营用量大盘"等高频读需求,可在 Pull 之上**另建**投影,不与本设计冲突。) --- ## 六、Blast Radius / 兼容性 - **meta**:新增 meta-api 端口 + meta-server 聚合器实现替换 `UnavailableMetaImpactFacade`(经 `@ConditionalOnMissingBean`/`@Primary` 平滑替换,参照 facade 替换先例)。`MetaSchemaImpactPreviewServiceImpl` 与 4 端点 API 契约**不变**。 - **content(P1)**:新增 `schema_key` 持久化=**Flyway 新增迁移(只增不改)** + 写入点补字段 + 贡献者适配器(只读本域)。对既有 planning 写链路低侵入。 - **knowledge/ai(P2+)**:仅在确属 schema 消费方时改;否则该维度贡献者返回 unknown(诚实)。 - **DB 迁移**:每阶段独立 `V__*.sql`(只增列/表,不改历史);Content 既有行 `schema_key` 为空→该维度对"历史无 key 行"按 unknown 计(不伪造),随写入逐步补全。 - **回滚**:端口未接消费方时聚合器 fail-closed=回到现状(治理端点阻断),无数据损坏面。 --- ## 七、风险 | 风险 | 说明 | 缓解 | |---|---|---| | 破坏性分析需字段级用量 | 仅计数不够,要判"字段被移除影响几个"需消费方记录用到哪些字段 | P1 评估 Content planning 的 content JSON 是否足以反推字段用量;不足则补字段使用快照 | | 版本快照一致性 | 消费方仅记 version、不记 key/hash,Meta 版本变更后难追溯旧版影响 | 基础层补 `schema_key`(+可选 draft_hash 快照),使消费实例自证用的哪个 schema | | 跨 BC 扇出延迟 | preview 同步扇出多 BC | 低频 admin 可接受;贡献者查询走本域索引;超时则该维度 unknown(不阻塞他维度、不伪造) | | 维度归属不清 | Knowledge/AI 是否真消费 schema 未证实(grounding 显示其不持久化) | open item 1:先证实再决定是否纳入,避免给不消费 schema 的 BC 强加端口 | | 特征工程蔓延 | 多 BC 改写入链路 | 严格分阶段、每阶段独立可验收;未做维度诚实 fail-closed | --- ## 八、验收标准(达成定义) - 端口层:`MetaSchemaUsageContributorApi` 在 meta-api;聚合器替换 Unavailable 后 **BcBoundaryArchTest 仍 0 违例**(Meta 不直连他域 DAL/application)。 - P1(Content):真实 PG IT——种真实 planning/work 实例(带 schema_key)→ `previewMetaSchemaDraftImpact` 返回**真实 Content 计数**;无消费实例→0(真实 0,非伪造);未接入维度→unknown/fail-closed;治理端点在"仅 Content 受影响"下可走通 preview→publish。 - 反假绿:未持久化 schema_key 的历史行不被计入"已知用量"(按 unknown),杜绝把"没数据"伪装成"0 影响"。 --- ## 九、Open Items(需人类/后续确认) 1. **Knowledge/AI/Export 是否真消费 MetaSchema?** grounding 显示三者均不持久化 schema 引用。需确认:impact summary 的这 3 维度是真实业务需求,还是 over-modeled 的 VO?若不消费,贡献者端口只需 Content(+视情况 Export),大幅缩小范围。 2. **破坏性分析的精度要求**:impact 只需"受影响实例数",还是必须"字段级破坏(移除/可见性)"?后者决定基础层是否要存字段使用快照(成本差异大)。 3. **是否接受分阶段期间"部分维度 unknown"的 preview 放行治理动作?** 即:只要已接入维度真实、未接入维度诚实 unknown,是否允许 admin 据此 publish?(关乎 fail-closed 的粒度策略。) 4. **`schema_key` 回填策略**:历史 planning 行无 key,是否需要一次性回填脚本(若 version→key 可推断),还是只对新写入生效、历史按 unknown。 5. 端口命名/归属与现有 `MetaImpactFacade` 的关系(保留 facade 作聚合门面 vs 直接重构)。 --- ## 十、决策确认(2026-06-20,人类拍板) | 议题 | 决策 | 影响 | |---|---|---| | 方向(§一.3 / §五) | **Pull 按需查询** | 各 BC 查本域、Meta 聚合;无投影表/回填/一致性窗口 | | 维度范围(open #1) | **保留全 5 维度**(Work/Planning/KnowledgeProjection/AIContext/Export) | 5 维度均须出**真实**贡献者;非 Content-only | | 破坏分析精度(open #2) | **字段级破坏分析** | 基础层须持久化**每实例的字段使用快照**,能算"移除某字段影响 N 实例"——成本高 | | fail-closed 粒度(open #3) | **要求全维度真实才放行** | 治理 4 端点须等**全 5 维度真实**(含非消费维度的"已验证真实 0")才解阻;不接受"部分 unknown 放行" | **诚实张力(须在执行版厘清,不回避)**:本组合=**最大范围 + 最高成本 + 价值最晚兑现**。 - 实证(2026-06-19/20 复核):Content 仅存 `schemaVersion`(无 `schema_key`);Knowledge/AI/Export 的 DAL **零 schema 引用**。在"全 5 维度 + 字段级 + 全真实才放行"下,这意味着对每个维度必须二选一并给出**实证**: - **真实消费建模**:该维度确消费 MetaSchema → 基础层补 `schema_key` + 字段使用快照,贡献者出真实计数;或 - **已验证 0 贡献者**:实证该维度确**不消费** MetaSchema → 贡献者返回**已验证真实 0**(非 unknown),并留实证注释。 - "全维度真实才放行"=治理端点在最后一个维度落地前**持续阻断**(分阶段建设、价值末期兑现);执行版须明确各维度归类(消费建模 vs 已验证 0)与落地顺序。 - 维度真实消费厘清正由 grounding(2026-06-20)调查中;执行版据其结论对 5 维度逐一定性。 > 下一步:据 grounding 结论写**执行版** `docs/agent-specs/2026-06-20-meta-schema用量投影-execution.md`(含各维度定性、数据契约=贡献者端口 API + 各 BC 用量/字段快照表、Flyway 迁移、分阶段步骤、每维度真实 PG IT 验收、回滚)。