oh-my-muse/docs/memorys/2026-06-07-P1R7dMarketSourceOwnerPropagation真实链路.md

15 KiB
Raw Blame History

P1R7d Market Source Owner Propagation 真实链路

日期2026-06-07

结论

P1R-7d Market source owner propagation 主体实现、V19 SQL、focused tests、P1R mixed executable gates、V19 Flyway _test、dependency tree gate、reactor build、隔离 coverage scanner 与 protected diff gate 已形成进入修复后 fresh implementation review 的证据。

修复后 fresh implementation review 已双 PASSPascal spec/correctness review PASSMill quality/data-integrity/testing review PASS均无 P0/P1/P2 blocker。

当前仍不能写 completed。本轮证据只代表 Market governance terminal fact -> Market publish outbox -> Market worker -> EventsPublishApi -> muse_unified_event -> /app-api/muse/events 对资产发布者可见的链路推进到 needs_verification 证据层,不代表 Events / P1R-7 / Market completed。

本轮未修改 OpenAPI、coverage scanner 或真实 coverage 报告。

已验证事实

工作区与保护文件

  • 正确 worktree/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.
  • 受保护文件最终 git diff --quiet -- ... 返回 exit 0
    • 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

本轮实现范围

  • Market server 新增直接依赖 muse-module-events-api
  • 新增 Market 本域 publish outbox
    • MuseMarketEventPublishOutboxDO
    • MuseMarketEventPublishOutboxMapper
    • MarketEventPublishOutboxService
    • MarketEventPublishOutboxServiceImpl
    • MarketEventPayloads
    • MarketEventPublishWorker
    • MuseMarketEventsProperties
    • MuseMarketEventsConfiguration
  • AdminMarketGovernanceServiceImpl.applyGovernanceAction 在治理动作 muse_market_governance_action 落库后,同事务创建 Market Events publish outbox。
  • command replay 不补历史 outbox。
  • 新增 V19 migrationmuse-cloud/sql/muse/V19__extend_market_events_publish_outbox.sql

Review 反馈与修复

  • Pasteur fresh implementation spec review 返回 FAIL两个有效问题已修复
    • V19 schema、DO、Mapper 补齐 source_command_idactor_user_idpreview_idrequest_hash
    • commandId/outboxId 幂等 key 改为 tenantId|actionId|ownerUserId|governance_action 的 SHA-256 前 32 位。
  • Kant fresh quality/data-integrity review 返回 FAIL两个有效问题已修复
    • Flyway IT baseInsertSql() 补齐四个 NOT NULL 字段,避免负向 insert 假绿。
    • payload validator 从“任意字符串 message”收紧为安全消息 allowlist。
  • Tesla fresh implementation spec review 返回 FAIL两个有效问题已修复
    • muse.market.events.publish-worker.max-attemptclaim-timeout-seconds 从执行版配置合同落到 MuseMarketEventsPropertiesoutbox service 写入配置化 maxAttemptworker claim 使用配置化超时时间。
    • payload timestamp 从 governance action createTime 派生,缺失时才回退当前时间,避免事件时间不可审计。
  • Volta fresh quality/data-integrity review 曾返回 PASS但该 PASS 发生在 Tesla 修复前;由于后续修改了 outbox service、worker、properties 和测试Volta PASS 已失效,不能计入最终 PASS gate。
  • 旧 Pasteur/Kant/Tesla/Volta 均不能计入最终 PASS gate。
  • 修复后 fresh implementation spec/correctness reviewPascalPASS无 P0/P1/P2 blocker残余非阻塞风险claim SQL 不在领取阶段过滤 attempt_count < max_attempt,但 worker 会在 claim 后判断耗尽并转 dead_letterE2E 仍是 focused harness不是真实 HTTP/SSE + 真实 DB 全链路dependency 单测主要读 direct POM后续最终 gate 应保留 dependency tree 原始输出。
  • 修复后 fresh implementation quality/data-integrity/testing reviewMillPASS无 P0/P1/P2 blocker残余非阻塞风险可后续把 sourceCommandId / actorUserId / previewId / requestHash 的 pre-insert 校验前移到 service可后续把 insertIgnore 收窄到指定 conflict target 或在 insert=0 且 action/command 均查不到时记录 error若未来审计要求精确同源时间可统一 EventsPublishReqDTO.emittedAt 与 payload timestamp

实现边界

  • 第一切片只发布 delist / recallnotification/governance_action
  • recall 第一切片只发布一条 market_governance_action notificationmuse_market_source_status_event 只作为事实旁证和后续扩展点。
  • SSE 可见 owner 是资产发布者 ownerUserId,不是 admin actor也不是 target owner。
  • payload exact allowlist
    • 顶层只允许 type/message/resourceRef/timestamp
    • resourceRef 只允许 resourceType/resourceId
    • message 只允许 资产已下架 / 资产已召回
    • payloadSummary.resourceRef.resourceId 保持 Number/Long 语义。
    • EventsPublishReqDTO.resourceId 仍按 Events DTO 合同使用 String。
  • 禁止发布授权快照、handoff token、target owner、admin note、error stack、完整 actionSnapshot。
  • request_hash 只作为 outbox 幂等/审计字段保存,不进入 Events payload。
  • worker 默认配置关闭:muse.market.events.publish-worker.enabled=false
  • 终态回写使用 publish_status='running' AND attempt_count=#{claimedAttemptCount} 防止过期 claim 覆盖新终态。

Reactor build

muse-cloud 执行:

JAVA_HOME=$(/usr/libexec/java_home -v 21) mvn -o clean install -DskipTests -Dspring-boot.repackage.skip=true

结果exit 0BUILD SUCCESS62/62 modules successFinished at 2026-06-07T20:36:27+08:00

Market focused tests

执行:

JAVA_HOME=$(/usr/libexec/java_home -v 21) mvn -o test -pl muse-module-market/muse-module-market-server -am -Dtest=AdminMarketGovernanceServiceTest,MarketEventPublishOutboxServiceTest,MarketEventPublishWorkerTest -Dsurefire.failIfNoSpecifiedTests=false

结果exit 028 tests passfailures/errors/skipped 均为 0。

surefire XML 证明以下目标类实际运行且 test count > 0

测试类 tests failures errors skipped
AdminMarketGovernanceServiceTest 11 0 0 0
MarketEventPublishOutboxServiceTest 6 0 0 0
MarketEventPublishWorkerTest 11 0 0 0

覆盖点:

  • delist / recall 成功治理动作会调用 Market Events outbox service。
  • command replay 不补历史 outbox。
  • invalid enum / invalid preview / CAS blocker 不创建 outbox。
  • outbox service 创建安全 payloadresourceRef.resourceId 是数值型。
  • duplicate command/action notification 返回既有 outbox不重复创建。
  • unsupported action / invalid owner 不创建 outbox。
  • payload invalid fail-closed抛出固定错误码 MARKET_EVENTS_PAYLOAD_INVALID,且不 insert outbox。
  • unsafe message 被 fail-closed且不调用 EventsPublishApi。
  • outbox service 把配置化 maxAttempt 写入 outbox默认值为 5。
  • payload timestamp 使用 governance action createTime,缺失时才回退当前时间。
  • Market outbox service 不依赖 EventsPublishApi
  • worker disabled 不 claim。
  • worker claim 使用配置化 claimTimeoutSeconds;默认值为 60。
  • accepted -> published。
  • duplicate accepted 回放同一 event identity。
  • rejected / blocked -> dead_letter。
  • CommonResult error 非最后一次 -> retryable最后一次 -> dead_letter。
  • API exception 非最后一次 -> retryable最后一次 -> dead_letter。
  • invalid payload 在 worker 侧 fail-closed dead_letter。
  • terminal status update 必须携带 claim attempt ownership。
  • terminal update 返回 0 时记录 stale claim warning。

P1R mixed executable gates

一次旧类名命令只实际运行 29 个测试;该结果已丢弃,不计入最终 evidence。修正为真实存在的 14 个测试类后重新执行:

JAVA_HOME=$(/usr/libexec/java_home -v 21) mvn -o test -pl muse-server -am -Dtest=P1rMarketEventsPublishMigrationSqlTest,P1rMarketEventsPublishDependencyTest,P1rMarketEventsPublishEndToEndTest,P1rKnowledgeEventsPublishMigrationSqlTest,P1rKnowledgeEventsPublishDependencyTest,P1rKnowledgeEventsPublishEndToEndTest,P1rAiEventsPublishMigrationSqlTest,P1rAiEventsPublishDependencyTest,P1rAiEventsPublishEndToEndTest,P1rApiCoverageReportTest,P1rEventsRealApiGateTest,P1rEventsRouteOwnershipTest,P1rAiRealApiGateTest,P1rAiRouteOwnershipTest -Dsurefire.failIfNoSpecifiedTests=false

结果exit 056 tests passfailures/errors/skipped 均为 0。

surefire XML 证明以下目标类实际运行且 test count > 0

测试类 tests failures errors skipped
P1rMarketEventsPublishMigrationSqlTest 3 0 0 0
P1rMarketEventsPublishDependencyTest 2 0 0 0
P1rMarketEventsPublishEndToEndTest 4 0 0 0
P1rKnowledgeEventsPublishMigrationSqlTest 3 0 0 0
P1rKnowledgeEventsPublishDependencyTest 2 0 0 0
P1rKnowledgeEventsPublishEndToEndTest 5 0 0 0
P1rAiEventsPublishMigrationSqlTest 4 0 0 0
P1rAiEventsPublishDependencyTest 2 0 0 0
P1rAiEventsPublishEndToEndTest 4 0 0 0
P1rApiCoverageReportTest 5 0 0 0
P1rEventsRealApiGateTest 5 0 0 0
P1rEventsRouteOwnershipTest 4 0 0 0
P1rAiRealApiGateTest 6 0 0 0
P1rAiRouteOwnershipTest 7 0 0 0

新增 Market gate 覆盖:

  • V19 SQL 静态 migration gate。
  • Market server 依赖 Events API不依赖 Events server。
  • Events server 不反向依赖 AI / Knowledge / Market / Member / Content server。
  • Market outbox -> worker -> EventsPublishServiceImpl -> muse_unified_event focused E2E。
  • asset publisher owner 可见admin actor 不可见,非 owner 不可见。
  • recall 只产生一条 governance_action notification。
  • blocked publish 进入 outbox dead_letter 且 SSE 不可见。
  • stale claim terminal update 因 attempt 不匹配被忽略。
  • AI / Knowledge / Events 既有 P1R gates 不回退。

Flyway _test

执行命令包含:

-Dtest=P1rMarketEventsPublishFlywayMigrationIT
-Dflyway.postgresql.transactional.lock=false
-Dp1r.flyway.locations=filesystem:sql/muse
-Dp1r.flyway.url=jdbc:postgresql://<host>:<port>/muse_p1r7d_events_publish_test
-Djava.net.useSystemProxies=false
-DsocksProxyHost=
-Dhttp.proxyHost=
-Dhttps.proxyHost=

结果exit 0P1rMarketEventsPublishFlywayMigrationIT tests=4、failures=0、errors=0、skipped=0。

关键输出:

flyway_success=true
flyway_url=jdbc:postgresql://<host>/muse_p1r7d_events_publish_test
flyway_locations_requested=filesystem:sql/muse
flyway_locations_effective=filesystem:/Users/qingse/.config/superpowers/worktrees/oh-my-muse/dev-1.0.0/muse-cloud/sql/muse
migrations_executed=19
successful_migration_count=19
target_schema_version=19
flyway_latest=19:extend market events publish outbox
schema_version=19
v19_table=muse_market_event_publish_outbox
v19_indexes=idx_muse_market_event_publish_outbox_claim,idx_muse_market_event_publish_outbox_owner_status,idx_muse_market_event_publish_outbox_action
v19_constraints=uk_muse_market_event_publish_outbox_id,uk_muse_market_event_publish_outbox_command,uk_muse_market_event_publish_outbox_action_notification,chk_muse_market_event_publish_outbox_event_type,chk_muse_market_event_publish_outbox_notification_type,chk_muse_market_event_publish_outbox_action_type,chk_muse_market_event_publish_outbox_status,chk_muse_market_event_publish_outbox_owner,chk_muse_market_event_publish_outbox_attempt_count,chk_muse_market_event_publish_outbox_max_attempt
v19_triggers=trg_muse_market_event_publish_outbox_update_time

Flyway IT 覆盖:

  • 只允许 _test 数据库。
  • JDBC URL 不允许携带 credential query parameters。
  • V19 table / indexes / constraints / trigger 存在。
  • V19 required columns 包含 source_command_idactor_user_idpreview_idrequest_hash,且为 NOT NULL。
  • 非法 event_type / notification_type / action_type / publish_status / owner_user_id <= 0 的真实 insert 被 PostgreSQL 拒绝。

Dependency tree gate

执行:

JAVA_HOME=$(/usr/libexec/java_home -v 21) mvn -o dependency:tree -pl muse-module-market/muse-module-market-server -Dincludes=cn.iocoder.cloud:muse-module-events-api,cn.iocoder.cloud:muse-module-events-server -DoutputType=text
JAVA_HOME=$(/usr/libexec/java_home -v 21) mvn -o dependency:tree -pl muse-module-events/muse-module-events-server -Dincludes=cn.iocoder.cloud:muse-module-ai-server,cn.iocoder.cloud:muse-module-knowledge-server,cn.iocoder.cloud:muse-module-market-server,cn.iocoder.cloud:muse-module-member-server,cn.iocoder.cloud:muse-module-content-server -DoutputType=text

结果:

  • Market server dependency tree 明确包含 cn.iocoder.cloud:muse-module-events-api:jar:2026.04-SNAPSHOT:compile
  • Market server dependency tree 未命中 muse-module-events-server
  • Events server dependency tree 对 AI / Knowledge / Market / Member / Content server 过滤无输出。

Coverage scanner

scanner 只在隔离副本运行,未在真实 worktree 写 coverage 报告。

隔离副本:

/tmp/p1r7d-final-coverage-scan.nhBVhM

执行:

python3 muse-cloud/scripts/p1r-audit-api-coverage.py --check

结果exit 0并只在隔离副本中生成 coverage JSON/Markdown。

隔离副本 summary

completedOperations=100
needsVerificationOperations=133
incompleteOperations=0
genericPersistenceOperations=0
ssePlaceholderOperations=0
events.streamEvents=dedicated/needs_verification
marketOperations=32
marketStatuses=dedicated/needs_verification

真实 worktree 受保护 coverage JSON/Markdown diff 仍为空。

静态检查

执行:

git diff --check

结果exit 0无 whitespace error。

推断

基于 focused tests、P1R mixed executable gates、V19 Flyway _test、dependency tree、reactor build、隔离 coverage scanner、protected diff 和 git diff --check 的组合证据,可以判断 P1R-7d Market source owner propagation 应用层链路已具备进入 fresh implementation review 的 needs_verification 证据。

由于 Pascal/Mill 已 fresh 双 PASS可以推断 P1R-7d Market source owner propagation implementation evidence 已收口到 needs_verification。该推断不代表 Events / P1R-7 / Market completed也不代表可以自动提交或 push。

假设

  • 当前 _test PostgreSQL 环境和 ~/.config/muse-repo/infra.env 仍代表本地 Flyway 验证环境。
  • Events 既有 EventsPublishApi 与 SSE visible query 合同不在 P1R-7d 中修改。
  • P1R-7d 不要求补 Market OpenAPI coverage 状态到 completed

下一步

  1. 按逻辑分组准备提交,但提交和 push 仍需用户明确批准。
  2. 提交前再次确认 protected diff、git diff --checkgit status --short --branch
  3. 双 PASS 后仍只允许收口到 needs_verification,不得自动推进 completed。