只推进 Market 4 个 operation-level completed approval,保持 market domain-level allowlist 关闭,并保留剩余 28 个 Market operation 为 needs_verification。
9.6 KiB
P1R Market 状态推进
日期:2026-06-11
结论
本轮只推进 Market 第一批 4 个 operation-level completed approval:
market:getMarketplaceAssetmarket:listMarketplaceCategoriesmarket:favoriteAssetmarket:unfavoriteAsset
Market 仍不是整域 completed。listMarketplaceAssets、listMarketplaceRecommendations 以及 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}/favoriteDELETE /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.jsondocs/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_attrigger 存在。- 同 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 +
_testDB,不是 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 已双 PASS:Raman 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、listMarketplaceAssets与listMarketplaceRecommendations继续 needs_verification、OpenAPI diff 仅限 favorite/unfavorite requiredX-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,推荐单独处理:
listMarketplaceAssets:先补 pageNo/pageSize 1..100 边界与防全量查询证据。listMarketplaceRecommendations:先解决 OpenAPI 个性化推荐语义与 fallback 排序实现的合同不一致。- publish/review/governance 13 个 operation:另写执行版冻结范围、Events outbox 边界和 fresh runtime evidence。
- purchase/install/handoff/governanceImpact:必须先补目标 owner 消费闭环与 Account 读侧 E2E。
- appeal/projection:不能把申诉审计、治理 outbox 和 Account projection 混成一个 completed 闭环。