# P1R Account Completed Approval 审阅版
日期:2026-06-11
## 结论
不建议把 Account 33 个 operation 一次性整域推进 `completed`。
推荐把 Account Completed Approval 拆成 operation-level 或证据切片推进:先审批 Account 本域已经形成闭环的读写与审计切片;New-API、FileService/download、call attribution 外部来源、Market purchase/license/publish projection 等跨 owner 链路继续保持 `dedicated / needs_verification`,直到有真实 runtime 或明确验收替代边界。
本审阅版只冻结 Account completed approval 的范围判断、证据缺口、推荐审批粒度和后续执行版要求。不修改 OpenAPI,不修改 scanner,不修改 coverage report,不修改业务实现,也不把 Account 或其它 domain 推进 `completed`。
```mermaid
flowchart TB
Start["当前 coverage
Account 33 dedicated / needs_verification"] --> Review["Account completed approval 审阅版
冻结证据标准"]
Review --> Split{"是否整域 33/33 completed?"}
Split -->|否,推荐| OpLevel["按证据切片 operation-level approval"]
Split -->|是,不推荐| DomainLevel["domain-level approval
需 New-API/FileService/Market/Attribution 全闭环"]
OpLevel --> Exec["执行版
列出可审批 operation 与保留 needs_verification operation"]
Exec --> FreshReview["fresh spec/scope review
fresh quality/feasibility review"]
FreshReview --> UserApproval{"用户明确批准
Account 状态推进?"}
UserApproval -->|否| Stay["保持 Account 33 needs_verification"]
UserApproval -->|是| Change["最小修改 scanner/report/gates
运行 focused + P1R + _test + XML 防空跑"]
```
## 当前事实状态
工作区:
```text
/Users/qingse/.config/superpowers/worktrees/oh-my-muse/dev-1.0.0
```
当前分支与远端同步,HEAD 为:
```text
df26bd9 test(p1r): 收口 Meta remaining 5 completed approval 门禁
```
当前 coverage summary:
```text
total=233
completed=117
needsVerification=116
incomplete=0
genericPersistence=0
ssePlaceholder=0
```
当前按 domain 聚合:
```text
account total=33 completed=0 needsVerification=33
ai total=41 completed=41 needsVerification=0
content total=51 completed=0 needsVerification=51
events total=1 completed=1 needsVerification=0
knowledge total=59 completed=59 needsVerification=0
market total=32 completed=0 needsVerification=32
meta total=16 completed=16 needsVerification=0
```
Account 33 个 operation 当前全部为 `dedicated / needs_verification`:
| operationId | Method | Path | 当前状态 |
|---|---|---|---|
| `adminCreateCallAttributionJob` | `POST` | `/admin-api/muse/account/call-attribution-jobs` | `dedicated / needs_verification` |
| `adminGetCallAttributionJob` | `GET` | `/admin-api/muse/account/call-attribution-jobs/{jobId}` | `dedicated / needs_verification` |
| `adminGetIntegrationCallByCorrelation` | `GET` | `/admin-api/muse/account/integration-calls/by-correlation/{correlationId}` | `dedicated / needs_verification` |
| `adminListNewApiBindings` | `GET` | `/admin-api/muse/account/new-api-bindings` | `dedicated / needs_verification` |
| `adminListPurchaseRecords` | `GET` | `/admin-api/muse/account/purchase-records` | `dedicated / needs_verification` |
| `adminListUsageRecords` | `GET` | `/admin-api/muse/account/usage-records` | `dedicated / needs_verification` |
| `adminListAccountUsers` | `GET` | `/admin-api/muse/account/users` | `dedicated / needs_verification` |
| `adminGetBalanceSnapshots` | `GET` | `/admin-api/muse/account/users/{userId}/balance-snapshots` | `dedicated / needs_verification` |
| `adminGetUserEntitlements` | `GET` | `/admin-api/muse/account/users/{userId}/entitlements` | `dedicated / needs_verification` |
| `adminCreateNewApiBinding` | `POST` | `/admin-api/muse/account/users/{userId}/new-api-binding` | `dedicated / needs_verification` |
| `adminListQuotaAdjustments` | `GET` | `/admin-api/muse/account/users/{userId}/quota-adjustments` | `dedicated / needs_verification` |
| `adminCreateQuotaAdjustment` | `POST` | `/admin-api/muse/account/users/{userId}/quota-adjustments` | `dedicated / needs_verification` |
| `adminCreateQuotaRequest` | `POST` | `/admin-api/muse/account/users/{userId}/quota-requests` | `dedicated / needs_verification` |
| `getAppBalanceSnapshots` | `GET` | `/app-api/muse/account/balance-snapshots` | `dedicated / needs_verification` |
| `appDownloadExport` | `GET` | `/app-api/muse/account/downloads/{credentialId}` | `dedicated / needs_verification` |
| `getAppEntitlements` | `GET` | `/app-api/muse/account/entitlements` | `dedicated / needs_verification` |
| `appCreateExportTask` | `POST` | `/app-api/muse/account/export-tasks` | `dedicated / needs_verification` |
| `appGetExportTask` | `GET` | `/app-api/muse/account/export-tasks/{taskId}` | `dedicated / needs_verification` |
| `appGetIntegrationCallByCorrelation` | `GET` | `/app-api/muse/account/integration-calls/by-correlation/{correlationId}` | `dedicated / needs_verification` |
| `appListLicenses` | `GET` | `/app-api/muse/account/licenses` | `dedicated / needs_verification` |
| `getAppNewApiBinding` | `GET` | `/app-api/muse/account/new-api-binding` | `dedicated / needs_verification` |
| `appRecheckNewApiBinding` | `POST` | `/app-api/muse/account/new-api-binding/recheck` | `dedicated / needs_verification` |
| `appListPublishRecords` | `GET` | `/app-api/muse/account/publish-records` | `dedicated / needs_verification` |
| `appListPurchases` | `GET` | `/app-api/muse/account/purchases` | `dedicated / needs_verification` |
| `appCreateQuotaRequest` | `POST` | `/app-api/muse/account/quota-requests` | `dedicated / needs_verification` |
| `appGetQuotaRequest` | `GET` | `/app-api/muse/account/quota-requests/{requestId}` | `dedicated / needs_verification` |
| `appListSecurityEvents` | `GET` | `/app-api/muse/account/security-events` | `dedicated / needs_verification` |
| `appGetSecurityEvent` | `GET` | `/app-api/muse/account/security-events/{eventId}` | `dedicated / needs_verification` |
| `appAcknowledgeSecurityEvent` | `POST` | `/app-api/muse/account/security-events/{eventId}/acknowledge` | `dedicated / needs_verification` |
| `getAppUsage` | `GET` | `/app-api/muse/account/usage` | `dedicated / needs_verification` |
| `getCurrentUser` | `GET` | `/app-api/muse/me` | `dedicated / needs_verification` |
| `getProfile` | `GET` | `/app-api/muse/profile` | `dedicated / needs_verification` |
| `updateProfile` | `PATCH` | `/app-api/muse/profile` | `dedicated / needs_verification` |
## 已验证实现证据
### Account owner 与入口
Account owner 当前位于 `muse-module-member` 的 Account 子域,没有独立 `muse-module-account`。
现有 dedicated Controller 覆盖 Account 33 个 operation:
- `AdminAccountNewApiController`
- `AdminAccountUserController`
- `AdminAccountUsageController`
- `AdminAccountPurchaseController`
- `AppAccountNewApiController`
- `AppAccountEntitlementController`
- `AppAccountMarketRecordController`
- `AppAccountExportController`
- `AppAccountSecurityController`
- `AppAccountProfileController`
这些 Controller 均通过 `AccountApiVersionGuard.requireVersion(...)` 校验 `X-API-Version`,并调用 Account 子域 Service,不再走旧 `MuseContractPersistenceService` 兜底。
管理端入口使用 `@PreAuthorize` 绑定 `muse:account:*` 权限;App 端入口使用 `getLoginUserId()` 作为当前 owner。
### Account 本域服务与持久化
Account 已有本域 Service / Guard / DAL:
- `AccountProfileServiceImpl`
- `AccountEntitlementServiceImpl`
- `AccountQuotaServiceImpl`
- `AccountUsageServiceImpl`
- `AccountNewApiBindingServiceImpl`
- `AccountAttributionServiceImpl`
- `AccountMarketRecordServiceImpl`
- `AccountExportServiceImpl`
- `AccountSecurityServiceImpl`
- `AccountCommandServiceImpl`
- `AccountAuditServiceImpl`
- `AccountEventPublishOutboxServiceImpl`
- `AccountEventPublishWorker`
- `AccountApiVersionGuard`
- `AccountOwnerGuard`
- `AccountDownloadGuard`
- `AccountQuotaGuard`
- Account DO / Mapper / Convert 文件
P1R-3 已把 Account 从 `generic_persistence / incomplete` 推进为 `dedicated / needs_verification`,并删除旧 Account 合同兜底 Controller。
### 数据库与迁移证据
V11 Account Real API schema 已存在:
- `muse-cloud/sql/muse/V11__extend_account_real_api_schema.sql`
V11 追加 Account owner 自有事实,包括:
- `muse_account_command`
- `muse_account_audit`
- `muse_account_profile`
- `muse_account_balance_snapshot`
- `muse_account_quota_request`
- `muse_account_integration_call`
- `muse_account_call_attribution_job`
- `muse_account_call_attribution_item`
- `muse_account_export_task`
- `muse_account_download_credential`
- `muse_account_security_event_ack`
- `muse_account_record_projection`
历史留痕记录 V11 已在真实 PostgreSQL test 库通过 Flyway:
```text
PostgreSQL 17.10
flyway_success=true
migrations_executed=11
target_schema_version=11
flyway_latest=11:extend account real api schema
v11_tables=12
account_index_count=47
```
V20 Account Events publish outbox 已存在:
- `muse-cloud/sql/muse/V20__extend_account_events_publish_outbox.sql`
历史留痕记录 V20 已在真实 `_test` 库通过 Flyway:
```text
flyway_success=true
migrations_executed=20
successful_migration_count=20
target_schema_version=20
flyway_latest=20:extend account events publish outbox
v20_table=muse_account_event_publish_outbox
```
这些迁移证据证明 DDL / Flyway 可执行性和 outbox schema 约束,不等同于 Account 33 个 API 全部具备 completed-grade runtime 证据。
### P1R-7e Account quota alert 证据
P1R-7e 已形成 Account quota adjustment terminal fact 到 Events SSE 的 needs-verification evidence:
```text
AccountQuotaServiceImpl.adminCreateQuotaAdjustment
-> muse_member_entitlement_audit_log(change_type=quota_adjustment)
-> muse_account_event_publish_outbox
-> AccountEventPublishWorker
-> EventsPublishApi
-> muse_unified_event
-> /app-api/muse/events 对 accountUserId 可见
```
历史验证包括:
- Member focused tests 36/36 pass。
- P1R mixed executable gates 73/73 pass。
- Account focused + P1R mixed XML 合计 109 tests,failures/errors/skipped 均为 0。
- `P1rAccountEventsPublishFlywayMigrationIT` 4/4 pass。
- Dependency tree gate 证明 Member server 依赖 `muse-module-events-api`,不依赖 `muse-module-events-server`。
当前 worktree 可见的 Surefire XML 只覆盖部分 Account P1R gate:
```text
P1rAccountRealApiGateTest 4/4
P1rAccountRouteOwnershipTest 4/4
P1rAccountEventsPublishMigrationSqlTest 3/3
P1rAccountEventsPublishDependencyTest 2/2
P1rAccountEventsPublishEndToEndTest 4/4
```
`P1rAccountEventsPublishFlywayMigrationIT` 与 Member focused tests 的 XML 是历史留痕证据,当前 worktree 不能直接引用为 fresh Account completed approval 证据。后续执行版必须重新运行并读取 XML,不能复用历史 XML 口径。
该证据可支持后续把 `adminCreateQuotaAdjustment` 作为 Account operation-level completed approval 的第一候选,但不能自动覆盖全部 Account 33 个 operation。
## 关键缺口
### 缺口 1:New-API runtime 未闭合
`NewApiAccountFacade` 定义了绑定和 recheck 的外部边界;默认 `UnavailableNewApiAccountFacade` 抛出 `ACCOUNT_NEW_API_UNAVAILABLE`,注释明确当前 worktree 没有真实 New-API runtime 配置,不能伪造绑定成功或重验任务。
因此以下 operation 不能仅凭当前 dedicated 实现直接 completed:
- `adminListNewApiBindings`
- `adminCreateNewApiBinding`
- `getAppNewApiBinding`
- `appRecheckNewApiBinding`
- `adminCreateQuotaRequest`
- `appCreateQuotaRequest`
- `appGetQuotaRequest`
- `adminGetIntegrationCallByCorrelation`
- `appGetIntegrationCallByCorrelation`
其中读侧 operation 可能有本地投影读取证据,但 create/recheck/request/correlation 相关 completed approval 必须说明真实 New-API runtime、失败关闭、超时、重试、correlation 与 attribution 口径。
### 缺口 2:FileService / 导出下载真实交付未闭合
`AccountFileServiceFacade` 默认返回 unavailable;注释明确 Account 只定义任务、凭证和下载校验,不接管真实文件生成或存储。
`AccountExportServiceImpl` 已有 fail-closed 行为:
- 高敏导出缺少可信 step-up proof 时拒绝。
- FileService 异常收敛为 unavailable。
- completed 必须有 fileRef、downloadExpiresAt 和 Account HMAC secret。
- 下载凭证消费具备 owner、过期、撤销、consumed、sourceBlocked 原子门禁。
但这仍不能证明真实文件或对象存储交付。因此以下 operation 暂不应 completed:
- `appCreateExportTask`
- `appGetExportTask`
- `appDownloadExport`
除非执行版补齐真实 FileService / 对象存储成功路径、失败路径、下载字节、凭证一次性消费和审计证据。
### 缺口 3:Call attribution 外部来源未闭合
`AccountAttributionServiceImpl` 的 create 路径只建立 job 队列事实,并明确真实归因执行由后续 job/transition 路径接管。外部归因来源不可用时会形成失败或补偿建议,而不是 completed-grade 归因成功。
因此以下 operation 不能整批 completed:
- `adminCreateCallAttributionJob`
- `adminGetCallAttributionJob`
执行版必须证明真实 attribution source 或明确 operation completed 口径只覆盖“创建 queued job + 可查询失败关闭状态”,否则应保持 `needs_verification`。
### 缺口 4:Market purchase/license/publish projection 依赖跨 owner 一致性
P1R-3 已固定 Account 视角使用 `muse_account_record_projection(record_type=purchase/license/publish)` 作为查询读模型;`muse_market_account_projection` 只是 Market 侧 sync/outbox 状态,不是 Account 查询读模型。
以下 operation 需要 Market 主流程和 Account projection 一致性证据:
- `adminListPurchaseRecords`
- `appListPurchases`
- `appListLicenses`
- `appListPublishRecords`
它们不能用 Market 事件传播或 Account projection 表存在来直接 completed。执行版必须证明 purchase/license/publish 上游 owner 写入、projection 同步、tenant/owner 隔离和 stale projection 风险。
### 缺口 5:安全事件与高敏导出源事实不足
`MemberSecurityEventDO` 有读侧、详情、ack 和脱敏转换;但 P1R-7e 审阅已验证,高敏导出生产安全事件路径当前被 `normalizeRequest` fail-closed 阻断,不能作为第一切片 source fact。
以下 operation 若要 completed,必须证明安全事件真实生产路径,而不是只证明读侧和 ack:
- `appListSecurityEvents`
- `appGetSecurityEvent`
- `appAcknowledgeSecurityEvent`
### 缺口 6:缺少本轮 fresh Account completed approval gate
当前 `P1rAccountRealApiGateTest` 仍明确禁止 Account operation 标记为 `completed`,并要求 33 个 operation 保持 `dedicated / needs_verification`。
当前 scanner 的 completed 白名单没有包含 Account domain 或 Account operation;已批准范围仍限于 AI / Knowledge domain,以及 Events / Meta 的 operation-level allowlist。未获批准的 Account completed 会被 scanner 拒绝。
后续执行版必须先明确用户批准范围,再把 gate 改成审批后口径:
- 仅允许 approved operation 从 `needs_verification` 变为 `completed`。
- 未批准 operation 必须继续 `dedicated / needs_verification`。
- Account 不能自动加入 domain-level completed allowlist。
- Market / Content 仍不能被连带推进。
## 推荐审批粒度
### 推荐:Account operation-level approval
第一批候选不应超过以下本域闭合较强的 operation:
```text
getCurrentUser
getProfile
updateProfile
adminListAccountUsers
adminGetUserEntitlements
getAppEntitlements
adminGetBalanceSnapshots
getAppBalanceSnapshots
getAppUsage
adminListUsageRecords
adminCreateQuotaAdjustment
adminListQuotaAdjustments
```
其中 `adminCreateQuotaAdjustment` 证据最强,因为 P1R-7e 已额外证明 quota adjustment terminal fact 可以进入 Account outbox 并发布到 Events。
但上述候选仍必须由执行版逐项验证 Controller、Service、DAL、权限、owner/tenant 隔离、幂等、审计、错误路径、XML 防空跑和真实 `_test` 证据。审阅版不直接批准这些 operation completed。
### 不推荐:Account domain-level approval
除非执行版能一次性补齐:
- 真实 New-API binding / recheck / quota request runtime。
- 真实 FileService / 对象存储导出下载。
- 真实 call attribution source 或明确可验收替代口径。
- Market purchase/license/publish 到 Account projection 的端到端一致性。
- security event 生产路径和 ack 的 owner/tenant 证据。
否则 Account 33/33 domain-level completed 会把外部闭环缺口包装成已完成。
## 非目标
- 不修改 7 个 OpenAPI:
- `docs/api-contracts/account/openapi.yaml`
- `docs/api-contracts/ai/openapi.yaml`
- `docs/api-contracts/content/openapi.yaml`
- `docs/api-contracts/events/openapi.yaml`
- `docs/api-contracts/knowledge/openapi.yaml`
- `docs/api-contracts/market/openapi.yaml`
- `docs/api-contracts/meta/openapi.yaml`
- 不修改 `muse-cloud/scripts/p1r-audit-api-coverage.py`。
- 不修改 `docs/superpowers/reports/p1r-api-coverage.json`。
- 不修改 `docs/superpowers/reports/p1r-api-coverage.md`。
- 不修改 Account 业务实现。
- 不把 Account 33 个 operation 推进 `completed`。
- 不把 Account 加入 domain-level completed allowlist。
- 不推进 Market / Content / 总 P1R completed。
- 不把 P1R-7e quota alert source owner evidence 当作 Account 整域 completed 证据。
## 后续执行版必须包含
1. Account 33 operation 的完整清单、当前状态和目标审批状态。
2. 第一批候选 operation 的逐项 evidence map:Controller、Service、DAL、权限、版本头、owner/tenant 隔离、审计、幂等、失败路径。
3. 明确哪些 operation 继续 `needs_verification`,以及原因。
4. scanner approval 模型:只允许 operation-level allowlist,不允许 Account domain-level allowlist,除非执行版证明 33/33 全闭环。
5. `P1rAccountRealApiGateTest` 从禁止 completed 到审批后 partial completed gate 的修改策略。
6. `P1rApiCoverageReportTest` summary 期望变更策略,必须只提升用户批准的 Account operation 数。
7. Account focused tests 的 required class 清单与最低 XML tests 数;执行版必须 fresh rerun `P1rAccountEventsPublishFlywayMigrationIT` 与 Member focused tests,不能只引用历史留痕。
8. P1R mixed gates:包含 Account gate、coverage report gate,以及用于证明非目标 Market / Content 不被推进的 gate。
9. 真实 PostgreSQL `_test`:至少覆盖 V1-V20 clean migrate;如新增 Account completed approval Flyway IT,应验证 V11/V20 表、索引、约束、trigger、非法 insert 拒绝。
10. 外部 runtime 验收:New-API / FileService / Market projection / attribution source 对应 operation 若不具备真实验收,必须保持 `needs_verification`。
11. protected diff gate:7 个 OpenAPI 在批准前后都必须保持空 diff。
12. allowed-diff gate:覆盖 unstaged、staged、untracked,并使用 `git -c core.quotePath=false`。
13. rollback 策略:撤回 scanner allowlist、coverage report、gate test 和新增 memory,恢复目标 operation 为 `dedicated / needs_verification`。
## 验收标准
本审阅版可以视为完成的条件:
1. 文件写入 `docs/agent-specs/2026-06-11-P1RAccountCompletedApproval审阅版.md`。
2. `.agent` 记录 Account completed approval 审阅版状态。
3. `git diff --check` 通过。
4. OpenAPI、scanner、coverage report 无 diff。
5. 文档只定义审阅路线,不进入执行版或实现。
6. fresh spec/scope review PASS。
7. fresh quality/feasibility review PASS。
## 待确认项
1. 是否确认 Account 第一轮不做 domain-level 33/33 completed approval。
2. 是否确认优先走 operation-level approval,并从本域闭合较强的 profile / entitlement / usage / quota adjustment 切片开始。
3. 是否确认 New-API、FileService/download、call attribution external source、Market projection、安全事件生产路径在没有真实 runtime 证据前继续保持 `needs_verification`。
4. 是否确认审阅版 fresh 双 review PASS 后,再写 Account completed approval 执行版。