oh-my-muse/docs/memorys/2026-06-11-P1RMarket状态推进.md
zizi 00327749a2 test(p1r): 收口 Market 第一批 completed approval 门禁
只推进 Market 4 个 operation-level completed approval,保持 market domain-level allowlist 关闭,并保留剩余 28 个 Market operation 为 needs_verification。
2026-06-11 18:56:54 +08:00

9.6 KiB
Raw Blame History

P1R Market 状态推进

日期2026-06-11

结论

本轮只推进 Market 第一批 4 个 operation-level completed approval

  • market:getMarketplaceAsset
  • market:listMarketplaceCategories
  • market:favoriteAsset
  • market:unfavoriteAsset

Market 仍不是整域 completed。listMarketplaceAssetslistMarketplaceRecommendations 以及 purchase/install/handoff/governance/publish/review/appeal/projection 相关 28 个 Market operation 继续 dedicated/needs_verification

本轮未修改 Market 业务实现,未修改数据库迁移,未把 market 加入 domain-level completed allowlist。

工作区与基线

工作区:

/Users/qingse/.config/superpowers/worktrees/oh-my-muse/dev-1.0.0

基线 HEAD

f18116a test(p1r): 收口 Account 第一批 completed approval 门禁

实施前 coverage summary

233	127	106	0	0	0

实施后 coverage summary

233	131	102	0	0	0

实施后 Market 状态:

completed=4
needs_verification=28

允许变更与实际变更

OpenAPI 只修改:

  • docs/api-contracts/market/openapi.yaml

变更内容只是在:

  • POST /app-api/muse/marketplace/assets/{assetId}/favorite
  • DELETE /app-api/muse/marketplace/assets/{assetId}/favorite

增加 required X-Command-Id header。原因是 Java Controller / Service 已强制校验 command id而原 OpenAPI 没有声明coverage report 因此误显示 requiresCommandId=false

scanner 只修改:

  • muse-cloud/scripts/p1r-audit-api-coverage.py

实际只追加 4 个 operation-level completed key没有把 market 加入 APPROVED_COMPLETED_DOMAINS

coverage report 已重新生成:

  • docs/superpowers/reports/p1r-api-coverage.json
  • docs/superpowers/reports/p1r-api-coverage.md

TDD 证据

RED 阶段先修改 gate 期望值和 Market operation 断言,在旧 scanner/report 下运行 focused P1R gates预期失败已出现

  • 失败点包括 expected completed=131 but was 127。
  • 失败点包括 Market expected 4 completed but was 0。
  • 该失败证明 gate 会阻止未获 scanner/report 支撑的 completed 推进。

GREEN 阶段完成 OpenAPI commandId 合同修正、scanner operation-level allowlist、report 重新生成和 focused evidence tests 后,目标验证通过。

MockMvc HTTP 入口 + DB 证据

新增:

  • muse-cloud/muse-server/src/test/java/cn/iocoder/muse/server/framework/api/P1rMarketDiscoveryFavoriteCompletedApprovalIT.java

验证方式:

  • 使用 Spring Mock web context + MockMvc
  • 使用真实 PostgreSQL _test 数据库。
  • 使用 Flyway clean/migrate V1-V15。
  • 密码只从环境变量读取,禁止通过 JVM system property 传入。

说明:这里的 HTTP 入口证据是执行版要求的 WebApplicationContext + MockMvc 请求路径证据,不是启动真实 socket 端口的 live servlet container 证据。

验证数据库:

muse_p1r_market_discovery_favorite_completed_approval_test

通过结果:

P1rMarketDiscoveryFavoriteCompletedApprovalIT: tests=9, failures=0, errors=0, skipped=0

覆盖内容:

  • 资产详情 happy path。
  • missing asset / invisible asset 不泄露详情、不写 command。
  • 分类聚合包含 fallback slot 与 unavailable exposure summary。
  • favorite 缺少 X-Command-Id 不写 DB。
  • favorite 写 active favorite 与 command重复 command 回放不重复写。
  • unfavorite 写 inactive不删除审计事实重复 command 回放不重复写。
  • missing/invisible target 对 favorite/unfavorite 不污染 command/favorite fact。

Flyway 证据

增强:

  • muse-cloud/muse-server/src/test/java/cn/iocoder/muse/server/framework/api/P1rMarketFlywayMigrationIT.java

验证数据库:

muse_p1r_market_completed_approval_test

通过结果:

P1rMarketFlywayMigrationIT: tests=4, failures=0, errors=0, skipped=0

验证内容:

  • V1-V15 clean migrate。
  • muse_market_favorite 表存在。
  • favorite user/asset/command 相关索引存在。
  • uk_muse_market_favorite_user_asset 唯一约束存在。
  • trg_muse_market_favorite_updated_at trigger 存在。
  • 同 tenant/user/asset duplicate insert 被 PostgreSQL 唯一约束拒绝SQLState 为 23505
  • 同 tenant/command_id duplicate insert 被 PostgreSQL partial unique index 拒绝SQLState 为 23505
  • favorite status 更新为 inactive 时,trg_muse_market_favorite_updated_at 会覆盖旧 update_time

额外组合验证:

P1rMarketDiscoveryFavoriteCompletedApprovalIT -> P1rMarketFlywayMigrationIT: tests=13, failures=0, errors=0, skipped=0
P1rMarketFlywayMigrationIT -> P1rMarketDiscoveryFavoriteCompletedApprovalIT: tests=13, failures=0, errors=0, skipped=0

该组合验证使用真实 PostgreSQL _test 库:

muse_p1r_market_combined_completed_approval_test

组合验证用于证明新增 Discovery IT 与增强 Flyway IT 对 p1r.flyway.url/user 的脱敏不会污染同一 Surefire JVM 内其他测试类。曾复现一次失败Discovery IT 先运行后Flyway IT 读到脱敏 system property报缺少原始 p1r.flyway.url。修复方式是在 Discovery IT 与 Flyway IT 中都保存原始 p1r.flyway.url/user,并在 @AfterAll 恢复;随后补充 -Dsurefire.runOrder=reversealphabetical,日志确认先跑 Flyway IT、再跑 Discovery IT合计 13/13 pass。

注意Surefire XML 的 <properties> 会记录原始 p1r.flyway.url host 与 p1r.flyway.user,未发现 password 泄露。raw XML 只能作为本地验证产物,不应直接外发;如需外发测试报告,应先清洗 host/user 或改造为不通过 JVM system property 传递 URL/user。

review 处理:

  • correctness reviewer 指出的 system property 污染为有效问题,已修复并用双向 combined IT 13/13 pass 关闭。
  • data/testing reviewer 提到“真正 HTTP”若理解为 socket 级 live server则当前证据不足。核对执行版后本轮要求是 WebApplicationContext/MockMvc + real mapper + _test DB不是 live socket server本文档已把措辞收窄为 MockMvc HTTP 入口,避免过度声明。
  • data/testing reviewer 提到 favorite status 没有 DB-level CHECK、asset_id/user_id 没有 FK。该问题属于后续 schema hardening本轮执行版明确禁止改迁移只能在现有 V8/V15 约束上补强 unique/index/trigger 断言,不把它扩成新增迁移。
  • 最终 fresh implementation review 已双 PASSRaman spec/correctness review PASS、Hubble data-integrity/testing review PASS均无 P0/P1/P2/P3 阻塞项。两名 reviewer 均确认 market 未进入 domain-level allowlist、只推进 4 个 market:* operation、Market 仍为 4 completed / 28 needs_verification、listMarketplaceAssetslistMarketplaceRecommendations 继续 needs_verification、OpenAPI diff 仅限 favorite/unfavorite required X-Command-Id、Market main/java 与 SQL diff 为空、13 个目标 XML 合计 85 tests 且 failures/errors/skipped 均为 0。非阻塞注意事项仍是 raw Surefire XML 暴露 host/user 但不含 password外发前需清洗。

focused gates

Market focused verification 通过:

AppMuseMarketplaceAssetControllerTest: tests=11, failures=0, errors=0, skipped=0
MarketAssetQueryServiceTest: tests=6, failures=0, errors=0, skipped=0
MarketFavoriteServiceTest: tests=7, failures=0, errors=0, skipped=0
MuseMarketAssetMapperTest: tests=2, failures=0, errors=0, skipped=0
P1rMarketMigrationSqlTest: tests=9, failures=0, errors=0, skipped=0
P1rMarketRouteOwnershipTest: tests=4, failures=0, errors=0, skipped=0
P1rMarketRealApiGateTest: tests=6, failures=0, errors=0, skipped=0
P1rApiCoverageReportTest: tests=6, failures=0, errors=0, skipped=0

跨域 P1R focused gates 通过:

P1rApiCoverageReportTest: tests=6, failures=0, errors=0, skipped=0
P1rMarketRealApiGateTest: tests=6, failures=0, errors=0, skipped=0
P1rEventsRealApiGateTest: tests=6, failures=0, errors=0, skipped=0
P1rAiRealApiGateTest: tests=7, failures=0, errors=0, skipped=0
P1rKnowledgeRealApiGateTest: tests=8, failures=0, errors=0, skipped=0

合计:

P1R mixed gates: 33/33 pass

scanner 与 diff 证据

scanner

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

结果:

Generated docs/superpowers/reports/p1r-api-coverage.json
Generated docs/superpowers/reports/p1r-api-coverage.md
233	131	102	0	0	0

Market operation 状态确认:

getMarketplaceAsset	completed	false
listMarketplaceCategories	completed	false
favoriteAsset	completed	true
unfavoriteAsset	completed	true
listMarketplaceAssets	needs_verification	false
listMarketplaceRecommendations	needs_verification	false

diff check

git diff --check: pass

OpenAPI diff

docs/api-contracts/market/openapi.yaml

仅包含 favorite/unfavorite 两个 operation 的 required X-Command-Id header。

后续边界

本轮完成后仍不得宣称:

  • Market 32/32 completed。
  • Content completed。
  • Account remaining 23 completed。
  • 总 P1R completed。

后续如果继续 Market completed approval推荐单独处理

  1. listMarketplaceAssets:先补 pageNo/pageSize 1..100 边界与防全量查询证据。
  2. listMarketplaceRecommendations:先解决 OpenAPI 个性化推荐语义与 fallback 排序实现的合同不一致。
  3. publish/review/governance 13 个 operation另写执行版冻结范围、Events outbox 边界和 fresh runtime evidence。
  4. purchase/install/handoff/governanceImpact必须先补目标 owner 消费闭环与 Account 读侧 E2E。
  5. appeal/projection不能把申诉审计、治理 outbox 和 Account projection 混成一个 completed 闭环。