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

263 lines
9.6 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.

# P1R Market 状态推进
日期2026-06-11
## 结论
本轮只推进 Market 第一批 4 个 operation-level completed approval
- `market:getMarketplaceAsset`
- `market:listMarketplaceCategories`
- `market:favoriteAsset`
- `market: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。
## 工作区与基线
工作区:
```text
/Users/qingse/.config/superpowers/worktrees/oh-my-muse/dev-1.0.0
```
基线 HEAD
```text
f18116a test(p1r): 收口 Account 第一批 completed approval 门禁
```
实施前 coverage summary
```text
233 127 106 0 0 0
```
实施后 coverage summary
```text
233 131 102 0 0 0
```
实施后 Market 状态:
```text
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 证据。
验证数据库:
```text
muse_p1r_market_discovery_favorite_completed_approval_test
```
通过结果:
```text
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`
验证数据库:
```text
muse_p1r_market_completed_approval_test
```
通过结果:
```text
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`
额外组合验证:
```text
P1rMarketDiscoveryFavoriteCompletedApprovalIT -> P1rMarketFlywayMigrationIT: tests=13, failures=0, errors=0, skipped=0
P1rMarketFlywayMigrationIT -> P1rMarketDiscoveryFavoriteCompletedApprovalIT: tests=13, failures=0, errors=0, skipped=0
```
该组合验证使用真实 PostgreSQL `_test` 库:
```text
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、`listMarketplaceAssets``listMarketplaceRecommendations` 继续 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 通过:
```text
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 通过:
```text
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
```
合计:
```text
P1R mixed gates: 33/33 pass
```
## scanner 与 diff 证据
scanner
```bash
python3 muse-cloud/scripts/p1r-audit-api-coverage.py --check
```
结果:
```text
Generated docs/superpowers/reports/p1r-api-coverage.json
Generated docs/superpowers/reports/p1r-api-coverage.md
233 131 102 0 0 0
```
Market operation 状态确认:
```text
getMarketplaceAsset completed false
listMarketplaceCategories completed false
favoriteAsset completed true
unfavoriteAsset completed true
listMarketplaceAssets needs_verification false
listMarketplaceRecommendations needs_verification false
```
diff check
```text
git diff --check: pass
```
OpenAPI diff
```text
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 闭环。