oh-my-muse/docs/agent-specs/2026-06-06-P1R7SourceOwnerPropagation全局审阅版.md

310 lines
18 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# P1R7 Source Owner Propagation 全局审阅版
## 结论
推荐把 P1R-7 后续主线从“AI 单 owner 先做”提升为“全局 source owner propagation 分层方案”,但实现仍必须按 owner 分阶段切片推进。
全局推荐方案:
1. Events owner 只负责统一事件投影、幂等、payload 校验、脱敏、可见性过滤和 SSE不反向读取任何 source owner 业务表。
2. 每个 source owner 只负责本域权威事实和本域 publish outboxworker 通过 `muse-module-events-api` 调用 `EventsPublishApi`
3. 不建立一个跨 owner 的中心 source 模块,也不让 Events server 直接拥有 source propagation 业务事实。
4. 当前 AI 第一切片实现草稿不能直接作为全局方案完成证据;它只能作为后续 P1R-7b 的候选实现素材,必须先按本全局方案复审和修订。
P1R-7 后续拆分建议:
| 阶段 | 目标 | 状态口径 |
|---|---|---|
| P1R-7b | 全局 propagation 规则冻结 + AI terminal event 第一 owner 切片 | 只推进 `needs_verification` 证据 |
| P1R-7c | Knowledge source status / projection event propagation | 只推进 `needs_verification` 证据 |
| P1R-7d | Market lifecycle / account projection / governance event propagation | 只推进 `needs_verification` 证据 |
| P1R-7e | Account(Member) security / entitlement / usage notification propagation | 只推进 `needs_verification` 证据 |
| P1R-7f | Content canonical change / block saved / export task event propagation | 只推进 `needs_verification` 证据 |
| P1R-7 completed approval | 对 P1R-7 做单独完成审批 | 必须用户单独批准 |
本审阅版不实现代码、不修改 OpenAPI、不修改 scanner、不修改 coverage JSON/Markdown不把 Events、P1R-7、Market 或任何 owner 标为 `completed`
## 已验证事实
### 工作区与状态
- 正确工作区为 `/Users/qingse/.config/superpowers/worktrees/oh-my-muse/dev-1.0.0`
- 当前分支为 `dev/1.0.0``git pull --ff-only origin dev/1.0.0` 输出 `Already up to date.`
- 当前 HEAD 为 `fa29753 test(p1r): 收口 Events SSE 门禁`
- 当前 worktree 有未提交的 P1R-7b AI outbox 草稿、V17 migration 草稿和 `docs/agent-specs/` 文档草稿;本审阅版不清理、不回退这些文件。
- 受保护文件当前定向 `git status --short` 无输出:
- `docs/api-contracts/market/openapi.yaml`
- `docs/api-contracts/ai/openapi.yaml`
- `docs/api-contracts/knowledge/openapi.yaml`
- `docs/api-contracts/events/openapi.yaml`
- `muse-cloud/scripts/p1r-audit-api-coverage.py`
- `docs/superpowers/reports/p1r-api-coverage.json`
- `docs/superpowers/reports/p1r-api-coverage.md`
### Coverage 与阶段边界
- 当前 coverage summary
- `totalOperations = 233`
- `completedOperations = 100`
- `needsVerificationOperations = 133`
- `incompleteOperations = 0`
- `genericPersistenceOperations = 0`
- `ssePlaceholderOperations = 0`
- Events 当前唯一 operation 为 `streamEvents GET /app-api/muse/events = dedicated / needs_verification`
- Market 当前 32 operations 均为 `dedicated / needs_verification`
- `docs/memorys/2026-06-05-P1R7aEventsSSE真实API收口.md` 明确 P1R-7a 未接入 source owner propagation未运行 source owner publish tests。
### 已有全局设计约束
- `CLAUDE.md` 明确本仓是设计文档 SSOT核心架构决策中 Source 传播采用“事件驱动 + 各模块自治”,统一实时通信为 SSE。
- `design-docs/架构-02-核心数据结构与双轨模型.md` 明确:来源 owner 发出状态变化事件,各消费模块监听事件并自行处理反应逻辑,不需要独立 source 模块。
- `design-docs/后端-03-关键流程实现与接口契约.md` 明确AI 调用、投影、索引、导出、评估、来源传播、New-API 归属和通知走异步任务,异步失败不得回滚已提交 Canonical。
- `docs/superpowers/plans/2026-06-05-P1R-7a-events-sse.md` 明确:跨 owner 发布模式固定为 source owner 本域 outbox + worker 调用 Events APIEvents server 不允许反向依赖 source owner server也不允许统一 SSE Controller 直接扫多域业务表。
### Events owner 当前能力
- `EventsPublishApi.publish(EventsPublishReqDTO)` 已存在于 `muse-module-events-api`
- `EventsPublishReqDTO` 已包含 `commandId``tenantId``ownerUserId``sourceOwner``sourceType``sourceId``sourceRevision``eventType``resourceType``resourceId``payloadSummary``emittedAt`
- `EventsPublishServiceImpl` 已按 commandId 优先、source tuple 次级做幂等回查。
- `EventsPublishServiceImpl` 使用 `insertIgnore`,避免用唯一约束异常作为正常幂等路径。
- `UnifiedEventMapper.selectVisibleEventsForOwner` 只查询 `publish_status = accepted`、同租户、同 ownerUserId、未删除、`sequenceNo` 大于 cursor 的事件。
- `EventsStreamServiceImpl` 将统一投影中的 `done` / `error` / `notification` 等事件转成 SSE。
### Source owner 当前能力差异
- AI 已有 `muse_ai_task_event` terminal fact、`MuseAiRuntimeJobDispatcher``MuseAiJobMapper.claimNextQueuedRuntimeJob()``FOR UPDATE SKIP LOCKED` worker 风格;当前未提交草稿新增了 AI event publish outbox但尚未按全局方案完成复审。
- Knowledge 已有 `muse_knowledge_source_event``muse_knowledge_projection_task`;当前 `MuseKnowledgeSourceEventService` 同步更新 projection 后把 task 记录为 `completed`,注释明确避免制造无执行者的 queued task。
- Market 已有 `MarketAccountProjectionOutboxService`,但接口只有 `recordSynced` / `recordBlocked`,职责是 Market 到 Member Account projection 的同步状态,不是 Events publish worker。
- Member(Account) 已有 `MemberSecurityEventDO``AccountIntegrationCallDO`、调用归因 job 和安全事件脱敏转换;当前 mapper 以查询/归因记录为主,未发现完整 Events publish outbox claim/retry/dead-letter 链路。
- Content 正式设计中已有 `BlockSavedEvent` outbox 方向,但本次只读未验证当前 Content 已有可直接复用到 Events 的 publish worker。
## 推断
- 全局 source propagation 的核心不是新增一个“大 source 服务”,而是冻结所有 owner 都必须遵守的事件发布合同、幂等合同、失败补偿合同和审计合同。
- 直接把当前 AI outbox 草稿继续推进,容易把“第一切片实现细节”误当成全局架构决策;应先用全局审阅版统一约束,再修订 AI 执行版。
- Market 的 projection outbox 名称容易误导;它当前表达的是 Market -> Account 读模型同步状态,不适合直接复用为 Events publish outbox。
- Knowledge 已有 source event但目前 projection task 同步完成,缺少异步 publish worker进入 P1R-7c 前需要先补本域发布补偿语义。
- Account security event 适合做用户通知类 propagation但必须先冻结安全 payload allowlist避免把设备、IP、风控原始详情或内部判断泄露到统一 SSE。
- Content 的 BlockSavedEvent 更接近内部 followup trigger不一定都应该进入用户 SSE需要先区分“内部领域事件”和“用户可见统一事件”。
## 假设
- P1R-7 后续允许在各 source owner 内新增 publish outbox 表或等价本域状态表。
- P1R-7 后续允许在 source owner server 中新增 `muse-module-events-api` 依赖,但不允许依赖 `muse-module-events-server`
- 当前 `EventsPublishReqDTO` envelope 足够承载后续 owner 的用户可见事件;如果后续发现字段不足,应另起 OpenAPI / contract 变更审批,而不是在实现里绕过。
- 当前 P1R-7 完成状态仍需用户单独批准;本方案只定义如何补证据链。
## 全局目标
1. 建立跨 owner 的统一 source propagation 规则,保证每个 owner 都按相同可审核链路发布事件。
2. 保持 source owner 自治:事实归 owner发布补偿归 owner统一可见投影归 Events。
3.`/app-api/muse/events` SSE 成为用户可见事件的统一出口,而不是跨表扫描器。
4. 为 P1R-7 completed approval 准备真实证据成功路径、幂等、失败、重试、dead-letter、权限、审计、数据库落库和 SSE 可见性。
本文只定义“用户可见 Events 发布链路”。它不替代正式 Source / Authorization 内部传播链路;内部来源状态、授权快照、传播到目标 owner 的阻断和禁用仍由正式设计中的 Source Status Event / Source Propagation Job 或等价本域机制承担。
## 非目标
1. 不建立独立 source 模块。
2. 不把 Events server 改造成 source owner 编排器。
3. 不让 Events server 反向依赖 AI / Knowledge / Market / Member / Content server。
4. 不把所有内部领域事件都暴露给 SSE。
5. 不复用职责不匹配的 Market Account projection outbox。
6. 不用修改 OpenAPI、scanner 或 coverage 报告掩盖缺口。
7. 不把当前 P1R-7b AI 草稿视为已完成实现。
8. 不推进 completed 状态。
## 推荐架构
```mermaid
flowchart LR
subgraph Owner["每个 Source Owner"]
Fact["本域权威事实<br/>Canonical 或 Shadow terminal fact"]
Outbox["本域 publish outbox<br/>queued/running/retryable/published/dead_letter"]
Worker["本域 worker<br/>claim + lease + retry"]
Fact --> Outbox --> Worker
end
Worker --> Api["EventsPublishApi<br/>events-api only"]
subgraph Events["Events Owner"]
Api --> Publish["幂等发布服务<br/>commandId + source tuple"]
Publish --> Store[("muse_unified_event<br/>accepted/rejected/blocked")]
Store --> Stream["SSE stream service<br/>tenant + owner + sequence"]
end
Stream --> Client["muse-studio fetch SSE"]
```
关键原则:
1. Source owner 只发布已经落库的、可审计的本域事实,不发布临时内存状态。
2. Source owner outbox 与本域事实绑定,但不能因为 Events 暂时不可用回滚已提交 Canonical。
3. Worker 不拼接自由 payload只从 outbox 固化的 allowlist payload 发布。
4. Events owner 只校验和投影,不反查 source owner 表补上下文。
5. SSE 只读 `muse_unified_event` accepted 事件,不直接查询 AI / Knowledge / Market / Account / Content 表。
## 全局发布合同
每个 owner 的发布请求必须满足:
| 字段 | 全局规则 |
|---|---|
| `commandId` | 稳定、短、幂等;推荐 `<owner>_evt:<sha256-32>`,长度不超过 128 |
| `tenantId` | 必填worker 线程必须恢复租户上下文 |
| `ownerUserId` | 必填;决定 SSE 可见性 |
| `sourceOwner` | 固定 owner 枚举,如 `ai``knowledge``market``account``content` |
| `sourceType` | 固定业务事实类型,不使用表名泄露内部结构 |
| `sourceId` | 本域事实稳定 id 或业务 id |
| `sourceRevision` | 本域事实版本;没有版本时使用明确占位,但 owner 执行版必须解释 |
| `eventType` | 只能使用 Events OpenAPI 已声明类型;新增类型必须另起合同审批 |
| `resourceType/resourceId` | 用户界面定位对象;不得代替 source tuple 幂等 |
| `payloadSummary` | 只包含 OpenAPI schema 允许字段和安全摘要 |
| `emittedAt` | 本域事实发生时间,不是 worker 发布时间 |
payload 全局禁令:
1. 不发布 prompt、provider request/response raw body、完整正文、知识资料原文、授权头、token、apiKey、secret、password。
2. 不发布内部风控原始规则、管理员备注原文、失败堆栈、数据库错误详情。
3. 不发布未在 OpenAPI 中声明的扩展字段。
4. 不把 `rejected``blocked` 事件作为 SSE 可见事件。
## 全局 outbox 状态机
```mermaid
stateDiagram-v2
[*] --> queued: owner fact 已落库并创建 publish intent
queued --> running: worker claim + lease
retryable --> running: retry 到期 claim
running --> running: stale lease reclaim
running --> published: Events accepted 或 duplicate accepted
running --> retryable: temporary failure
running --> dead_letter: payload invalid / rejected / blocked / retry exhausted
retryable --> dead_letter: retry exhausted
published --> [*]
dead_letter --> [*]
```
全局要求:
1. claim 必须是原子 SQL优先使用 `FOR UPDATE SKIP LOCKED` 或等价安全领取机制。
2. claim 必须包含 lease避免 crash-after-claim 后永久 running。
3. attempt 只在 claim 时递增,失败处理不得二次递增。
4. 幂等插入必须优先使用 `ON CONFLICT DO NOTHING` / `insertIgnore` + 回查不把唯一约束异常当正常路径PostgreSQL 同事务异常可能让事务进入 aborted 状态。
5. `dead_letter` 不能自动 replay只有确认是临时故障的记录才能被重置为 `retryable`
6. 所有状态转换必须有中文日志,至少包含 owner、tenantId、ownerUserId、source tuple、outboxId、attempt 和错误摘要。
7. owner 执行版必须显式冻结最小字段词汇:`max_attempt``next_retry_at``claim_expires_at`、固定退避策略、claim 索引和依赖树验证命令。
## 用户可见事件判定准则
只有同时满足以下条件的事件才进入统一 SSE
1. 用户需要实时感知该变化,且变化能影响当前用户下一步操作。
2. 事件 payload 可以被压缩成 OpenAPI 已声明 schema 内的安全摘要。
3. 事件不要求前端读取内部风控、授权、source propagation 或 worker 调度细节。
4. 事件 owner 能提供稳定 source tuple、幂等 commandId 和 ownerUserId。
默认不进入统一 SSE 的事件:
1. 只服务内部 followup trigger 的领域事件,例如 `BlockSavedEvent`
2. projection rebuild、source propagation target、retry job、worker heartbeat 等内部任务状态。
3. 需要完整正文、知识资料、provider raw body、授权详情或安全风控原始证据才能解释的事件。
## 阶段化路线
### P1R-7b全局规则冻结 + AI terminal event 第一切片
目标:
- 修订现有 AI 第一切片执行版,使其服从本全局方案。
- AI terminal `done/error` 通过本域 outbox + worker 发布到 Events。
- 修正当前草稿中可能存在的同事务唯一冲突异常风险,采用 `ON CONFLICT DO NOTHING` / insert-ignore + 回查。
- 证明 AI 只依赖 events-api不依赖 events-server。
不做:
- 不把 AI 以外 owner 混入 P1R-7b 实现。
- 不标 completed。
### P1R-7cKnowledge propagation
目标:
- 选择 Knowledge source status / projection summary 中最小用户可见事件。
- 在 Knowledge owner 内新增或复用 publish outbox 语义,补 claim/retry/dead-letter。
- 区分内部 projection task 和用户可见 Events notification。
不做:
- 不把同步完成的 projection task 伪装成异步 worker。
- 不发布知识资料原文。
### P1R-7dMarket propagation
目标:
- 覆盖 publish review、asset delist/recall、license/install/purchase 对用户可见状态的通知。
- 保留 Market Account projection outbox 的原职责,另建或扩展专门 Events publish outbox。
不做:
- 不把 Market 32 operations 标为 completed。
- 不让 Market 事件接管源作品、源智能体或源知识库事实 owner。
### P1R-7eAccount(Member) propagation
目标:
- 覆盖 security event、entitlement/quota notification、New-API attribution summary 中适合用户可见的事件。
- 复用既有安全事件脱敏转换,但新增统一 Events payload allowlist。
- 如果后续目标偏“用户通知”而不是“source status propagation”Account security event 可以作为 Knowledge 之后的低风险 second slice 备选。
不做:
- 不发布设备风控原始细节、IP 内部判断、接口调用原始日志或成本原始 authority。
### P1R-7fContent propagation
目标:
- 评估 BlockSavedEvent、export task、import task 中哪些应进入用户可见 SSE。
- 明确内部 followup trigger 与用户通知的分界。
不做:
- 不把正文保存的每次内部事件都推给 SSE。
- 不发布正文全文或 block content。
## 完成审批门槛
P1R-7 completed approval 必须另起任务,并至少具备:
1. Events owner 自身 gateroute ownership、OpenAPI schema、payload sanitizer、idempotency、SSE replay、frontend fetch SSE。
2. 至少覆盖 AI、Knowledge、Market、Account(Member)、Content 中被声明为 P1R source owner 的真实发布链路。
3. 每个 owner 都有成功、重复幂等、临时失败重试、retry exhausted、dead-letter、敏感 payload fail-closed、跨 owner 依赖方向测试。
4. PostgreSQL `_test` Flyway / migration 证据覆盖新增 outbox 表和 `muse_unified_event`
5. HTTP / MockMvc / SSE 或等价 focused E2E 证据证明当前用户只能看到同 tenant + ownerUserId 的 accepted 事件。
6. 审计或日志证据证明事件发布链路可追踪、可排查、可回放。
7. 用户明确批准从 `needs_verification` 推进到 `completed`
## 风险
- 抽象过早:如果现在先做共享 publish 库,可能在第二个 owner 前抽错接口;因此先冻结合同和测试模板,等 AI + Knowledge 两个 owner 通过后再抽小型 support module。
- 事务风险:同事务内 outbox 插入如果靠捕获唯一约束异常处理PostgreSQL 可能使事务不可继续;实现必须使用 insert-ignore 或先锁定事实行。
- Payload 风险:不同 owner 的“摘要”含义不同,必须逐 owner allowlist不允许泛化 Map 透传。
- 完成状态风险source propagation evidence 增加不等于 P1R-7 completedcompleted 必须另有审批。
- Dirty baseline 风险:当前 worktree 已有 AI 草稿后续执行前必须决定是修订沿用、拆分提交还是用户批准后重置对应草稿本审阅版不处理。P1R-7b 执行版修订并双 review PASS 前,当前 AI outbox / V17 / docs 草稿不得继续测试、提交、推送或作为完成证据。
## 待确认项
1. 是否确认以本文作为新的 P1R-7 source owner propagation 全局主线,替代此前 AI-only 审阅版作为最高层方案。
2. 是否确认 P1R-7b 仍从 AI terminal event 第一切片落地,但必须先修订执行版以符合本文全局规则。
3. 是否确认 completed approval 另起任务,当前所有阶段只推进 `needs_verification` 证据。
## 下一步
1. 对本文进行 fresh spec compliance review。
2. 对本文进行 fresh quality / feasibility review。
3. 双 PASS 后修订 `docs/agent-specs/2026-06-06-P1R7bSourceOwnerPropagation执行版.md`,把 AI 第一切片执行版降级为全局方案下的 P1R-7b 子计划。
4. P1R-7b 子计划双 review PASS 后,才允许处理当前 AI 草稿实现和后续 worker 任务。