15 KiB
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 已双 PASS:Pascal spec/correctness review PASS,Mill 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.yamldocs/api-contracts/ai/openapi.yamldocs/api-contracts/knowledge/openapi.yamldocs/api-contracts/events/openapi.yamlmuse-cloud/scripts/p1r-audit-api-coverage.pydocs/superpowers/reports/p1r-api-coverage.jsondocs/superpowers/reports/p1r-api-coverage.md
本轮实现范围
- Market server 新增直接依赖
muse-module-events-api。 - 新增 Market 本域 publish outbox:
MuseMarketEventPublishOutboxDOMuseMarketEventPublishOutboxMapperMarketEventPublishOutboxServiceMarketEventPublishOutboxServiceImplMarketEventPayloadsMarketEventPublishWorkerMuseMarketEventsPropertiesMuseMarketEventsConfiguration
AdminMarketGovernanceServiceImpl.applyGovernanceAction在治理动作muse_market_governance_action落库后,同事务创建 Market Events publish outbox。- command replay 不补历史 outbox。
- 新增 V19 migration:
muse-cloud/sql/muse/V19__extend_market_events_publish_outbox.sql。
Review 反馈与修复
- Pasteur fresh implementation spec review 返回 FAIL,两个有效问题已修复:
- V19 schema、DO、Mapper 补齐
source_command_id、actor_user_id、preview_id、request_hash。 commandId/outboxId幂等 key 改为tenantId|actionId|ownerUserId|governance_action的 SHA-256 前 32 位。
- V19 schema、DO、Mapper 补齐
- Kant fresh quality/data-integrity review 返回 FAIL,两个有效问题已修复:
- Flyway IT
baseInsertSql()补齐四个 NOT NULL 字段,避免负向 insert 假绿。 - payload validator 从“任意字符串 message”收紧为安全消息 allowlist。
- Flyway IT
- Tesla fresh implementation spec review 返回 FAIL,两个有效问题已修复:
muse.market.events.publish-worker.max-attempt与claim-timeout-seconds从执行版配置合同落到MuseMarketEventsProperties,outbox service 写入配置化maxAttempt,worker claim 使用配置化超时时间。- payload
timestamp从 governance actioncreateTime派生,缺失时才回退当前时间,避免事件时间不可审计。
- 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 review(Pascal)PASS,无 P0/P1/P2 blocker;残余非阻塞风险:claim SQL 不在领取阶段过滤
attempt_count < max_attempt,但 worker 会在 claim 后判断耗尽并转 dead_letter;E2E 仍是 focused harness,不是真实 HTTP/SSE + 真实 DB 全链路;dependency 单测主要读 direct POM,后续最终 gate 应保留 dependency tree 原始输出。 - 修复后 fresh implementation quality/data-integrity/testing review(Mill)PASS,无 P0/P1/P2 blocker;残余非阻塞风险:可后续把
sourceCommandId / actorUserId / previewId / requestHash的 pre-insert 校验前移到 service;可后续把insertIgnore收窄到指定 conflict target 或在 insert=0 且 action/command 均查不到时记录 error;若未来审计要求精确同源时间,可统一EventsPublishReqDTO.emittedAt与 payloadtimestamp。
实现边界
- 第一切片只发布
delist/recall的notification/governance_action。 recall第一切片只发布一条market_governance_actionnotification;muse_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 0,BUILD SUCCESS,62/62 modules success,Finished 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 0,28 tests pass,failures/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 创建安全 payload,
resourceRef.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。
CommonResulterror 非最后一次 -> 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 0,56 tests pass,failures/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_eventfocused E2E。 - asset publisher owner 可见,admin actor 不可见,非 owner 不可见。
recall只产生一条governance_actionnotification。- 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 0,P1rMarketEventsPublishFlywayMigrationIT 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_id、actor_user_id、preview_id、request_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。
假设
- 当前
_testPostgreSQL 环境和~/.config/muse-repo/infra.env仍代表本地 Flyway 验证环境。 - Events 既有
EventsPublishApi与 SSE visible query 合同不在 P1R-7d 中修改。 - P1R-7d 不要求补 Market OpenAPI coverage 状态到
completed。
下一步
- 按逻辑分组准备提交,但提交和 push 仍需用户明确批准。
- 提交前再次确认 protected diff、
git diff --check和git status --short --branch。 - 双 PASS 后仍只允许收口到
needs_verification,不得自动推进 completed。