- approve only appListSecurityEvents and appGetSecurityEvent at operation level - keep appAcknowledgeSecurityEvent needs_verification - add HTTP+DB completed approval IT and update coverage gates/docs
30 KiB
P1R Account Security Events Completed Approval 执行版
For agentic workers: REQUIRED SUB-SKILL: Use
superpowers:subagent-driven-developmentto implement this plan task-by-task only after fresh execution review double PASS and explicit user approval. Steps use checkbox syntax for tracking.
日期:2026-06-13
结论
本执行版只锁定 Account 用户安全事件只读 2 个 operation-level completed approval:
account:appListSecurityEvents
account:appGetSecurityEvent
本轮不把 account 加入 domain-level completed allowlist,不推进 Account 33/33 completed,不修改 OpenAPI,不修改 Account 业务实现,不修改 SQL migration。account:appAcknowledgeSecurityEvent 因 session_revoked 公开合同与当前实现不闭合,继续保持 needs_verification。
获批后目标 coverage summary 为:
total=233
completed=147
needsVerification=86
incomplete=0
genericPersistence=0
ssePlaceholder=0
Account 域目标状态为:
account total=33
completed=12
needsVerification=21
当前阶段只允许写执行方案并进入 fresh execution review。执行版 review 双 PASS 后,仍必须由用户再次明确批准审批清单、operation-level 边界、allowed diff 和 mixed gate 同步范围,才允许实施。
flowchart TB
Current["当前 Account<br/>10 completed / 23 needs_verification"] --> Exec["执行版<br/>锁定 Security Events read 2 ops"]
Exec --> Review["fresh execution spec/scope review<br/>fresh execution quality/testing review"]
Review --> Approval{"用户明确批准<br/>2 ops / operation-level / allowed diff / mixed gates"}
Approval -->|否| Stay["保持当前 coverage<br/>233/145/88"]
Approval -->|是| Red["TDD RED<br/>先改 gate 期望<br/>旧 report 必须失败"]
Red --> Runtime["HTTP + real DB _test<br/>owner + tenant + latest ack + no-write"]
Runtime --> Green["scanner operation allowlist<br/>regenerate report"]
Green --> Verify["focused tests + P1R mixed gates<br/>XML 防空跑 + protected diff"]
Verify --> FreshReview["fresh implementation review"]
当前事实
正确 worktree:
/Users/qingse/.config/superpowers/worktrees/oh-my-muse/dev-1.0.0
当前 HEAD:
304f665 test(p1r): 收口 Content Admin RiskAction completed approval 门禁
当前 coverage summary:
233 145 88 0 0 0
当前 domain 状态:
account completed=10 needsVerification=23
content completed=14 needsVerification=37
market completed=4 needsVerification=28
meta completed=16 needsVerification=0
events completed=1 needsVerification=0
当前目标 operation 状态:
appListSecurityEvents dedicated needs_verification false GET /app-api/muse/account/security-events
appGetSecurityEvent dedicated needs_verification false GET /app-api/muse/account/security-events/{eventId}
必须保持 needs_verification 的相关写命令:
appAcknowledgeSecurityEvent dedicated needs_verification true POST /app-api/muse/account/security-events/{eventId}/acknowledge
已验证的只读实现事实:
AppAccountSecurityController使用AccountApiVersionGuard.requireVersion(...)和getLoginUserId()。AccountSecurityServiceImpl.appListSecurityEvents按当前 owner + severity 查询安全事件,并合并最新 ack。AccountSecurityServiceImpl.appGetSecurityEvent按 eventId + owner 查询详情,并通过AccountConvert脱敏 IP / userAgent。AccountSecurityServiceImpl.requireUser()依赖MemberUserMapper.selectById;P1Rsql/muse当前 V1-V21 不创建member_user。SecurityEventAcknowledgeReqVO与 OpenAPI 当前包含session_revoked,但 OpenAPI 文案承诺真实 session revoke,当前实现只返回 fail-closed 文案;本执行版不推进 acknowledge。
执行边界
必须先获用户明确批准
实现前必须同时获得以下 4 项批准:
- 批准本轮只审批
account:appListSecurityEvents、account:appGetSecurityEvent两个 operation。 - 批准继续使用 operation-level approval,不把
account加入 domain-level completed allowlist。 - 批准按本执行版修改 scanner、coverage report、P1R gates、新增 Security Events HTTP+DB
_test、memory 和.agent。 - 批准同步 mixed gate 的 summary / Account / 非目标域防回退断言,目标为
233/147/86/0/0/0与 Account12 completed / 21 needs_verification。
未获上述批准前,不得实施本执行版。
本轮允许变更
获批后只允许修改以下路径:
muse-cloud/scripts/p1r-audit-api-coverage.pydocs/superpowers/reports/p1r-api-coverage.jsondocs/superpowers/reports/p1r-api-coverage.mdmuse-cloud/muse-server/src/test/java/cn/iocoder/muse/server/framework/api/P1rApiCoverageReportTest.javamuse-cloud/muse-server/src/test/java/cn/iocoder/muse/server/framework/api/P1rAccountRealApiGateTest.javamuse-cloud/muse-server/src/test/java/cn/iocoder/muse/server/framework/api/P1rEventsRealApiGateTest.javamuse-cloud/muse-server/src/test/java/cn/iocoder/muse/server/framework/api/P1rAiRealApiGateTest.javamuse-cloud/muse-server/src/test/java/cn/iocoder/muse/server/framework/api/P1rKnowledgeRealApiGateTest.javamuse-cloud/muse-server/src/test/java/cn/iocoder/muse/server/framework/api/P1rMarketRealApiGateTest.javamuse-cloud/muse-server/src/test/java/cn/iocoder/muse/server/framework/api/P1rContentRealApiGateTest.javamuse-cloud/muse-server/src/test/java/cn/iocoder/muse/server/framework/api/P1rMetaRealApiGateTest.javamuse-cloud/muse-server/src/test/java/cn/iocoder/muse/server/framework/api/P1rAccountSecurityEventsCompletedApprovalIT.javadocs/agent-specs/.agentdocs/agent-specs/2026-06-13-P1RAccountSecurityEventsCompletedApproval审阅版.mddocs/agent-specs/2026-06-13-P1RAccountSecurityEventsCompletedApproval执行版.mddocs/memorys/2026-06-13-P1RAccountSecurityEvents状态推进.md
AccountSecurityServiceTest、AppAccountSecurityControllerTest 以及既有 mapper/convert focused tests 只允许作为验证命令和 XML 防空跑证据被运行、读取,不列入本轮可修改路径。如 implementation 发现必须修改 Account 业务实现、OpenAPI、SQL migration、既有 focused tests、非批准 gate 或其它文件,必须停下说明原因并重新取得用户批准。
本轮禁止变更
- 不修改 7 个 OpenAPI。
- 不修改 Account main/java 业务实现来掩盖 coverage 缺口。
- 不新增或修改 SQL migration。
- 不把
account加入 domain-level completed allowlist。 - 不推进 Account 33/33 completed。
- 不推进
account:appAcknowledgeSecurityEvent。 - 不推进 Account remaining 21、Market remaining 28、Content remaining 37 或总 P1R completed。
- 不推进 New-API binding / recheck / quota request、FileService/export/download、call attribution、usage attribution、Market purchase/license/publish projection、integration-call 查询。
- 不把安全事件读证据写成安全事件所有生产来源 completed。
- 不通过 mock
MemberUserMapper或 production SQL 修改绕过member_user前置依赖。 - 不把 dedicated gate PASS、review PASS、文档结论或已有 Mockito 单测直接等同 completed。
审批清单
| operation key | Method | Path | 目标状态 | 完成证据边界 |
|---|---|---|---|---|
account:appListSecurityEvents |
GET |
/app-api/muse/account/security-events |
dedicated / completed |
MockMvc HTTP + 真实 PostgreSQL _test,覆盖 owner/tenant、severity、分页、latest ack、敏感字段不泄露、API version、read no-write |
account:appGetSecurityEvent |
GET |
/app-api/muse/account/security-events/{eventId} |
dedicated / completed |
MockMvc HTTP + 真实 PostgreSQL _test,覆盖 detail 脱敏、跨 owner/跨 tenant/missing 不可见、非数字 eventId、ack 合并、read no-write |
保持 needs_verification 的 Account operation
以下 21 个 operation 必须保持 dedicated / needs_verification:
account:adminCreateCallAttributionJob
account:adminGetCallAttributionJob
account:adminGetIntegrationCallByCorrelation
account:adminListNewApiBindings
account:adminListPurchaseRecords
account:adminListUsageRecords
account:adminCreateNewApiBinding
account:adminCreateQuotaRequest
account:appDownloadExport
account:appCreateExportTask
account:appGetExportTask
account:appGetIntegrationCallByCorrelation
account:appListLicenses
account:getAppNewApiBinding
account:appRecheckNewApiBinding
account:appListPublishRecords
account:appListPurchases
account:appCreateQuotaRequest
account:appGetQuotaRequest
account:appAcknowledgeSecurityEvent
account:getAppUsage
证据分层
| Evidence | 文件 / 测试 | 目的 |
|---|---|---|
| Operation inventory / coverage gate | P1rApiCoverageReportTest、P1rAccountRealApiGateTest 和 mixed gates |
证明只推进获批 2 个 operation,非目标 domain 不回退 |
Security Events HTTP+DB _test |
新增 P1rAccountSecurityEventsCompletedApprovalIT |
证明 2 个 read operation 经 MockMvc HTTP 入口访问真实 service / mapper / PostgreSQL _test 数据 |
| Tenant / schema gate | P1rAccountSecurityEventsCompletedApprovalIT 内验证 V1-V21 clean migrate 与 V2/V11 安全事件依赖 schema |
证明安全事件表、ack 表、索引、trigger、JSONB 和 tenant 字段在当前 live migration baseline 下真实可用 |
| Auth fixture gate | P1rAccountSecurityEventsCompletedApprovalIT 内创建 test-local member_user fixture |
满足 requireUser() 的真实 mapper 前置,但不计入 P1R schema evidence |
| App security context gate | P1rAccountSecurityEventsCompletedApprovalIT 内设置 app LoginUser 与 tenant context |
证明 owner 不能由请求参数覆盖,跨 owner / 跨 tenant 不可见 |
| No-write gate | P1rAccountSecurityEventsCompletedApprovalIT 对 read happy/error 前后做表快照 |
证明 list/detail 不写 security event、ack、command、audit 或 outbox |
| Focused unit/controller tests | AccountSecurityServiceTest、AppAccountSecurityControllerTest、mapper/convert tests |
支撑 service/controller contract,不替代 HTTP+DB _test |
TDD / 实施步骤
Task 1:Preflight 与 RED gate
- 确认当前 worktree:
git -c core.quotePath=false status --short --branch
期望:
## dev/1.0.0...origin/dev/1.0.0
允许存在本执行版和审阅版文档 diff;不得存在 OpenAPI、业务实现、SQL、scanner、coverage report 或 gate test 的未授权 diff。
- 确认当前 coverage:
jq -r '.summary | [.totalOperations,.completedOperations,.needsVerificationOperations,.incompleteOperations,.genericPersistenceOperations,.ssePlaceholderOperations] | @tsv' docs/superpowers/reports/p1r-api-coverage.json
jq -r '.operations[] | select(.domain=="account" and (.operationId=="appListSecurityEvents" or .operationId=="appGetSecurityEvent" or .operationId=="appAcknowledgeSecurityEvent")) | [.operationId,.implementationStatus,.completionStatus,(.requiresCommandId|tostring),.method,.path] | @tsv' docs/superpowers/reports/p1r-api-coverage.json
期望:
233 145 88 0 0 0
appListSecurityEvents dedicated needs_verification false GET /app-api/muse/account/security-events
appGetSecurityEvent dedicated needs_verification false GET /app-api/muse/account/security-events/{eventId}
appAcknowledgeSecurityEvent dedicated needs_verification true POST /app-api/muse/account/security-events/{eventId}/acknowledge
- TDD RED:先修改 P1R gate 期望值和 2 个 read operation completed 断言,但不修改 scanner/report。
RED 目标:
P1rApiCoverageReportTest期望 summarycompleted=147 / needsVerification=86。P1rAccountRealApiGateTest期望 Account12 completed / 21 needs_verification,2 个 read operation completed,appAcknowledgeSecurityEvent继续needs_verification。- 7 个 mixed gate 中所有硬编码 Account
10/23或 summary145/88的断言同步为12/21或147/86。
RED 命令:
cd muse-cloud
JAVA_HOME=$(/usr/libexec/java_home -v 21) PATH="$JAVA_HOME/bin:$PATH" \
mvn -o test -pl muse-server -am \
-Dtest=P1rApiCoverageReportTest,P1rAccountRealApiGateTest,P1rEventsRealApiGateTest,P1rAiRealApiGateTest,P1rKnowledgeRealApiGateTest,P1rMarketRealApiGateTest,P1rContentRealApiGateTest,P1rMetaRealApiGateTest \
-Dsurefire.failIfNoSpecifiedTests=false
期望:BUILD FAILURE。失败点必须来自旧 report 仍是 233/145/88 或 2 个 read operation 仍为 needs_verification;不得来自编译错误或无关测试失败。
Task 2:新增 Security Events HTTP+DB _test
- 新增:
muse-cloud/muse-server/src/test/java/cn/iocoder/muse/server/framework/api/P1rAccountSecurityEventsCompletedApprovalIT.java
测试上下文要求:
- 使用
@SpringBootTest(webEnvironment = MOCK)+WebApplicationContext+MockMvcBuilders.webAppContextSetup(...)。 - 真实
/app-api/muse/**前缀进入AppAccountSecurityController。 - 导入
MuseWebAutoConfiguration,并提供 test-localApiErrorLogCommonApistub,返回CommonResult.success(true),满足GlobalExceptionHandler依赖。 - 设置 app
LoginUser与 tenant context;请求参数中的userId或其它伪 owner 参数不得改变 owner。 - 使用真实
AccountSecurityServiceImpl、真实 mapper 和真实 PostgreSQL_test数据库;不得 mockMemberSecurityEventMapper或AccountSecurityEventAckMapper。 MemberUserMapper必须使用真实 mapper。由于sql/muse不包含member_user,测试可以在隔离_test库完成 Flyway migrate 后创建 test-localmember_userfixture 表并 seed 登录用户;该 fixture 只能作为requireUser()auth 前置,不计入 P1R schema evidence,不允许修改 production SQL。- test-local
member_userDDL 必须覆盖MemberUserDO、TenantBaseDO、BaseDO当前映射列,至少包含:id、mobile、password、status、register_ip、register_terminal、login_ip、login_date、nickname、avatar、name、sex、birthday、area_id、mark、point、tag_ids、level_id、experience、group_id、tenant_id、creator、create_time、updater、update_time、deleted。不得只建id/nickname等最小列,也不得通过修改 mapper 或 production SQL 回避真实MemberUserMapper.selectById。 - 注册真实 MyBatis tenant interceptor:
TenantLineInnerInterceptor+TenantDatabaseInterceptor(new TenantProperties())。 TARGET_VERSION="21",执行 V1-V21 clean migrate 后再创建 test-local auth fixture;Account 专属P1rAccountEventsPublishFlywayMigrationIT可以继续作为 V20 Account outbox 迁移证据复跑,但不能替代本 IT 的当前 live V21 baseline。- 数据库密码只能来自环境变量,禁止 JVM system property 或 JDBC query 参数传入。
- 保存并在
@AfterAll恢复p1r.flyway.url/p1r.flyway.usersystem property,避免污染同一 Surefire JVM 后续 Flyway 测试。
建议测试库:
muse_p1r_account_security_events_completed_approval_test
建议环境变量优先级:
P1R_ACCOUNT_SECURITY_EVENTS_COMPLETED_PASSWORD
P1R_ACCOUNT_COMPLETED_PASSWORD
P1R_FLYWAY_PASSWORD
MUSE_POSTGRES_PASSWORD
standalone 建库与运行前置:
source ~/.config/muse-repo/infra.env
export P1R_FLYWAY_PASSWORD="$MUSE_POSTGRES_PASSWORD"
export P1R_ACCOUNT_COMPLETED_PASSWORD="$MUSE_POSTGRES_PASSWORD"
export P1R_ACCOUNT_SECURITY_EVENTS_COMPLETED_PASSWORD="$MUSE_POSTGRES_PASSWORD"
export P1R_ACCOUNT_SECURITY_EVENTS_COMPLETED_APPROVAL_TEST_DB=muse_p1r_account_security_events_completed_approval_test
PGPASSWORD="$MUSE_POSTGRES_PASSWORD" psql \
-h "$MUSE_POSTGRES_HOST" \
-p "$MUSE_POSTGRES_PORT" \
-U "$MUSE_POSTGRES_USERNAME" \
-d postgres \
-tc "SELECT 1 FROM pg_database WHERE datname = '$P1R_ACCOUNT_SECURITY_EVENTS_COMPLETED_APPROVAL_TEST_DB'" | grep -q 1 || \
PGPASSWORD="$MUSE_POSTGRES_PASSWORD" psql \
-h "$MUSE_POSTGRES_HOST" \
-p "$MUSE_POSTGRES_PORT" \
-U "$MUSE_POSTGRES_USERNAME" \
-d postgres \
-c "CREATE DATABASE $P1R_ACCOUNT_SECURITY_EVENTS_COMPLETED_APPROVAL_TEST_DB"
必测矩阵:
- schema gate:
- V1-V21 clean migrate 成功,
migrationsExecuted=21。 muse_member_security_event、muse_account_security_event_ack存在。muse_member_security_event有 tenant_id、account_user_id、device_info JSONB、ip_address、acknowledged、acknowledged_at。muse_account_security_event_ack有 tenant_id、event_id、account_user_id、action、command_id、risk_summary JSONB。idx_muse_member_security_user、trg_muse_member_security_updated_at存在。uk_muse_account_security_event_ack_command、idx_muse_account_security_event_ack_user、idx_muse_account_security_event_ack_event、trg_muse_account_security_event_ack_updated_at存在。- test-local
member_userfixture 表存在,覆盖真实实体映射列,并只用于 seed 登录用户。
- V1-V21 clean migrate 成功,
appListSecurityEvents:- 同 tenant / same owner 返回 list。
- severity filter 只返回目标严重度。
- 只合并当前 owner 最新 ack。
- 返回摘要不泄露原始 IP / device_info。
- 跨 owner、跨 tenant 不可见。
- 缺少
X-API-Version不调用 service、不写库。 - read no-write:请求前后
muse_member_security_event、muse_account_security_event_ack、muse_account_command、muse_account_audit、muse_account_event_publish_outbox全表快照一致。 - no-write 快照必须使用
row_to_json(t)::text级别内容比对并按稳定键排序,至少按tenant_id, id排序;不能退化成只比较 row count。
appGetSecurityEvent:- detail 返回脱敏 sourceIp、deviceInfo.userAgent。
- 合并最新 ack 的 acknowledgedAt / acknowledgedAction。
- missing、非数字 eventId、跨 owner、跨 tenant 都返回 not found 语义且不泄露事件存在性。
- read no-write,使用与 list 相同的
row_to_json(t)::text全表快照集合。
最低 XML tests 数:建议 P1rAccountSecurityEventsCompletedApprovalIT >= 8。
Task 3:TDD GREEN,最小 scanner/report 状态推进
只修改 muse-cloud/scripts/p1r-audit-api-coverage.py:
- 不修改
APPROVED_COMPLETED_DOMAINS。 - 只向
APPROVED_COMPLETED_OPERATIONS追加:
account:appListSecurityEvents
account:appGetSecurityEvent
- 保持 completed 必须仍是
dedicated的校验。
生成 report:
python3 muse-cloud/scripts/p1r-audit-api-coverage.py --check
预期 summary:
total=233
completed=147
needsVerification=86
incomplete=0
genericPersistence=0
ssePlaceholder=0
预期 Account:
completed=12
needsVerification=21
Task 4:Account focused verification
运行 Account security focused tests:
source ~/.config/muse-repo/infra.env
export P1R_FLYWAY_PASSWORD="$MUSE_POSTGRES_PASSWORD"
export P1R_ACCOUNT_COMPLETED_PASSWORD="$MUSE_POSTGRES_PASSWORD"
export P1R_ACCOUNT_SECURITY_EVENTS_COMPLETED_PASSWORD="$MUSE_POSTGRES_PASSWORD"
export P1R_ACCOUNT_SECURITY_EVENTS_COMPLETED_APPROVAL_TEST_DB=muse_p1r_account_security_events_completed_approval_test
export P1R_ACCOUNT_SECURITY_EVENTS_COMPLETED_APPROVAL_JDBC_URL="jdbc:postgresql://${MUSE_POSTGRES_HOST}:${MUSE_POSTGRES_PORT}/${P1R_ACCOUNT_SECURITY_EVENTS_COMPLETED_APPROVAL_TEST_DB}"
PGPASSWORD="$MUSE_POSTGRES_PASSWORD" psql \
-h "$MUSE_POSTGRES_HOST" \
-p "$MUSE_POSTGRES_PORT" \
-U "$MUSE_POSTGRES_USERNAME" \
-d postgres \
-tc "SELECT 1 FROM pg_database WHERE datname = '$P1R_ACCOUNT_SECURITY_EVENTS_COMPLETED_APPROVAL_TEST_DB'" | grep -q 1 || \
PGPASSWORD="$MUSE_POSTGRES_PASSWORD" psql \
-h "$MUSE_POSTGRES_HOST" \
-p "$MUSE_POSTGRES_PORT" \
-U "$MUSE_POSTGRES_USERNAME" \
-d postgres \
-c "CREATE DATABASE $P1R_ACCOUNT_SECURITY_EVENTS_COMPLETED_APPROVAL_TEST_DB"
cd muse-cloud
JAVA_HOME=$(/usr/libexec/java_home -v 21) PATH="$JAVA_HOME/bin:$PATH" \
mvn -o test -pl muse-module-member/muse-module-member-server,muse-server -am \
-Dtest=AccountSecurityServiceTest,AppAccountSecurityControllerTest,AccountSecurityEventAckMapperTest,MemberSecurityEventMapperTest,AccountConvertTest,P1rAccountSecurityEventsCompletedApprovalIT,P1rAccountRealApiGateTest,P1rApiCoverageReportTest \
-Dflyway.postgresql.transactional.lock=false \
-Dp1r.flyway.locations=filesystem:sql/muse \
-Dp1r.flyway.url="$P1R_ACCOUNT_SECURITY_EVENTS_COMPLETED_APPROVAL_JDBC_URL" \
-Dp1r.flyway.user="$MUSE_POSTGRES_USERNAME" \
-Dp1r.account.security-events.completed-approval.jdbc-url="$P1R_ACCOUNT_SECURITY_EVENTS_COMPLETED_APPROVAL_JDBC_URL" \
-Dp1r.account.security-events.completed-approval.jdbc-user="$MUSE_POSTGRES_USERNAME" \
-Dsurefire.failIfNoSpecifiedTests=false
必须读取以下 XML 并检查 tests>0、failures=0、errors=0、skipped=0:
| Test class | 最低 tests |
|---|---|
AccountSecurityServiceTest |
8 |
AppAccountSecurityControllerTest |
6 |
AccountSecurityEventAckMapperTest |
4 |
MemberSecurityEventMapperTest |
2 |
AccountConvertTest |
8 |
P1rAccountSecurityEventsCompletedApprovalIT |
8 |
P1rAccountRealApiGateTest |
5 |
P1rApiCoverageReportTest |
6 |
AccountSecurityServiceTest、AccountSecurityEventAckMapperTest 中涉及 ack 或 session_revoked 的既有断言,只作为现状回归和 XML 防空跑证据,不计入本轮 completed evidence;appAcknowledgeSecurityEvent 仍必须保持 needs_verification。
如实现修改了 Account gate 测试数量,XML 检查的最低 tests 可高于上表,但不能低于上表。
建议使用以下 XML 防空跑脚本检查 Task 4、Task 5 和 Task 6 的目标 XML:
python3 - <<'PY'
from pathlib import Path
import sys
import xml.etree.ElementTree as ET
expected = {
"TEST-cn.iocoder.muse.module.member.application.account.AccountSecurityServiceTest.xml": 8,
"TEST-cn.iocoder.muse.module.member.controller.app.account.AppAccountSecurityControllerTest.xml": 6,
"TEST-cn.iocoder.muse.module.member.dal.mysql.account.AccountSecurityEventAckMapperTest.xml": 4,
"TEST-cn.iocoder.muse.module.member.dal.mysql.account.MemberSecurityEventMapperTest.xml": 2,
"TEST-cn.iocoder.muse.module.member.convert.account.AccountConvertTest.xml": 8,
"TEST-cn.iocoder.muse.server.framework.api.P1rAccountSecurityEventsCompletedApprovalIT.xml": 8,
"TEST-cn.iocoder.muse.server.framework.api.P1rAccountEventsPublishFlywayMigrationIT.xml": 4,
"TEST-cn.iocoder.muse.server.framework.api.P1rApiCoverageReportTest.xml": 6,
"TEST-cn.iocoder.muse.server.framework.api.P1rAccountRealApiGateTest.xml": 5,
"TEST-cn.iocoder.muse.server.framework.api.P1rEventsRealApiGateTest.xml": 5,
"TEST-cn.iocoder.muse.server.framework.api.P1rAiRealApiGateTest.xml": 7,
"TEST-cn.iocoder.muse.server.framework.api.P1rKnowledgeRealApiGateTest.xml": 8,
"TEST-cn.iocoder.muse.server.framework.api.P1rMarketRealApiGateTest.xml": 6,
"TEST-cn.iocoder.muse.server.framework.api.P1rContentRealApiGateTest.xml": 5,
"TEST-cn.iocoder.muse.server.framework.api.P1rMetaRealApiGateTest.xml": 4,
}
roots = [
Path("muse-module-member/muse-module-member-server/target/surefire-reports"),
Path("muse-server/target/surefire-reports"),
]
failures = []
for name, minimum in expected.items():
xml_path = next((root / name for root in roots if (root / name).exists()), None)
if xml_path is None:
failures.append(f"missing {name}")
continue
suite = ET.parse(xml_path).getroot()
tests = int(suite.attrib.get("tests", "0"))
failed = int(suite.attrib.get("failures", "0"))
errors = int(suite.attrib.get("errors", "0"))
skipped = int(suite.attrib.get("skipped", "0"))
if tests < minimum or failed or errors or skipped:
failures.append(f"{name}: tests={tests}, failures={failed}, errors={errors}, skipped={skipped}, minimum={minimum}")
if failures:
print("\n".join(failures))
sys.exit(1)
print("P1R Account Security Events XML gate passed")
PY
Task 5:Account Flyway _test gate
fresh rerun P1rAccountEventsPublishFlywayMigrationIT。使用独立 _test 库,不能使用生产库或非 _test 库:
source ~/.config/muse-repo/infra.env
export P1R_FLYWAY_PASSWORD="$MUSE_POSTGRES_PASSWORD"
export P1R_ACCOUNT_TEST_DB=muse_p1r_account_security_events_flyway_test
PGPASSWORD="$MUSE_POSTGRES_PASSWORD" psql \
-h "$MUSE_POSTGRES_HOST" \
-p "$MUSE_POSTGRES_PORT" \
-U "$MUSE_POSTGRES_USERNAME" \
-d postgres \
-tc "SELECT 1 FROM pg_database WHERE datname = '$P1R_ACCOUNT_TEST_DB'" | grep -q 1 || \
PGPASSWORD="$MUSE_POSTGRES_PASSWORD" psql \
-h "$MUSE_POSTGRES_HOST" \
-p "$MUSE_POSTGRES_PORT" \
-U "$MUSE_POSTGRES_USERNAME" \
-d postgres \
-c "CREATE DATABASE $P1R_ACCOUNT_TEST_DB"
cd muse-cloud
JAVA_HOME=$(/usr/libexec/java_home -v 21) PATH="$JAVA_HOME/bin:$PATH" \
mvn -o test -pl muse-server -am \
-Dtest=P1rAccountEventsPublishFlywayMigrationIT \
-Dflyway.postgresql.transactional.lock=false \
-Dp1r.flyway.locations=filesystem:sql/muse \
-Dp1r.flyway.url="jdbc:postgresql://$MUSE_POSTGRES_HOST:$MUSE_POSTGRES_PORT/$P1R_ACCOUNT_TEST_DB" \
-Dp1r.flyway.user="$MUSE_POSTGRES_USERNAME" \
-Djava.net.useSystemProxies=false \
-DsocksProxyHost= -DsocksProxyPort= \
-Dhttp.proxyHost= -Dhttp.proxyPort= \
-Dhttps.proxyHost= -Dhttps.proxyPort= \
-Dsurefire.failIfNoSpecifiedTests=false
必须检查 XML:
| Test class | 最低 tests |
|---|---|
P1rAccountEventsPublishFlywayMigrationIT |
4 |
Task 6:P1R mixed gate
运行 mixed gates:
cd muse-cloud
JAVA_HOME=$(/usr/libexec/java_home -v 21) PATH="$JAVA_HOME/bin:$PATH" \
mvn -o test -pl muse-server -am \
-Dtest=P1rApiCoverageReportTest,P1rAccountRealApiGateTest,P1rEventsRealApiGateTest,P1rAiRealApiGateTest,P1rKnowledgeRealApiGateTest,P1rMarketRealApiGateTest,P1rContentRealApiGateTest,P1rMetaRealApiGateTest \
-Dsurefire.failIfNoSpecifiedTests=false
必须读取以下 XML:
| Test class | 最低 tests |
|---|---|
P1rApiCoverageReportTest |
6 |
P1rAccountRealApiGateTest |
5 |
P1rEventsRealApiGateTest |
5 |
P1rAiRealApiGateTest |
7 |
P1rKnowledgeRealApiGateTest |
8 |
P1rMarketRealApiGateTest |
6 |
P1rContentRealApiGateTest |
5 |
P1rMetaRealApiGateTest |
4 |
每个 XML 均必须 failures=0、errors=0、skipped=0。
Task 7:报告与 diff gate
检查 summary:
jq -r '.summary | [.totalOperations,.completedOperations,.needsVerificationOperations,.incompleteOperations,.genericPersistenceOperations,.ssePlaceholderOperations] | @tsv' docs/superpowers/reports/p1r-api-coverage.json
预期:
233 147 86 0 0 0
检查 Account 12/21:
python3 - <<'PY'
import json
from collections import Counter
from pathlib import Path
data = json.loads(Path("docs/superpowers/reports/p1r-api-coverage.json").read_text())
counter = Counter(op["completionStatus"] for op in data["operations"] if op["domain"] == "account")
print(counter)
PY
预期:
Counter({'needs_verification': 21, 'completed': 12})
检查目标 operation:
jq -r '.operations[] | select(.domain=="account" and (.operationId=="appListSecurityEvents" or .operationId=="appGetSecurityEvent" or .operationId=="appAcknowledgeSecurityEvent")) | [.operationId,.implementationStatus,.completionStatus,(.requiresCommandId|tostring)] | @tsv' docs/superpowers/reports/p1r-api-coverage.json
预期:
appListSecurityEvents dedicated completed false
appGetSecurityEvent dedicated completed false
appAcknowledgeSecurityEvent dedicated needs_verification true
检查 OpenAPI protected diff:
git diff --quiet -- docs/api-contracts
git diff --cached --quiet -- docs/api-contracts
检查 business implementation 不被修改:
git diff --quiet -- muse-cloud/muse-module-member/muse-module-member-server/src/main/java
git diff --cached --quiet -- muse-cloud/muse-module-member/muse-module-member-server/src/main/java
检查 SQL migration 不被修改:
git diff --quiet -- muse-cloud/sql/muse
git diff --cached --quiet -- muse-cloud/sql/muse
检查 whitespace:
git diff --check
检查 allowed diff:
git -c core.quotePath=false status --short
输出只能包含本执行版允许路径。若出现 OpenAPI、业务实现、迁移或非批准 gate 文件,必须停止。
Task 8:memory 与 .agent
实现通过后新增:
docs/memorys/2026-06-13-P1RAccountSecurityEvents状态推进.md
内容必须记录:
- 批准的 2 个 Account operation。
- 保持
needs_verification的 21 个 Account operation 及原因。 appAcknowledgeSecurityEvent暂缓原因:session_revoked合同与实现不闭合。- scanner/report/gate 修改范围。
- 所有验证命令、结果、XML 计数、Flyway
_test库名。 - protected diff 与 allowed diff 结果。
- 明确说明不代表 Account 33/33 completed,不代表 Market/Content/总 P1R completed。
同时更新 docs/agent-specs/.agent,但只能记录事实,不写未验证结论。
Task 9:fresh implementation review
实现、验证和文档留痕后,必须派发两类 fresh reviewer:
- spec/correctness reviewer:检查 2 个 operation 是否严格匹配本执行版,21 个 operation 是否仍 needs_verification,Account domain allowlist 是否未新增。
- quality/data-integrity/testing reviewer:检查 HTTP+DB
_test、test-local auth fixture、scanner/report/gate、XML 防空跑、Flyway_test、protected diff、allowed diff、rollback 是否可靠。
双 PASS 前不得提交、push 或宣称 Account Security Events completed approval 已收口。
回滚策略
如实现后需要撤回:
- 从
APPROVED_COMPLETED_OPERATIONS移除 2 个account:*key。 - 重新运行:
python3 muse-cloud/scripts/p1r-audit-api-coverage.py --check
- 恢复 gate 期望:
summary completed=145
summary needsVerification=88
account completed=10
account needsVerification=23
- 删除或修订本轮 memory,保留失败原因。
- 重新运行 Account/P1R focused gates 和
git diff --check。
验收标准
执行版本身可以进入实现前批准点的条件:
- 本文件已写入
docs/agent-specs/2026-06-13-P1RAccountSecurityEventsCompletedApproval执行版.md。 .agent记录执行版当前状态。git diff --check通过。- OpenAPI、scanner、coverage report、业务实现、SQL migration 当前无新增 diff。
- fresh execution spec/scope review PASS。
- fresh execution quality/feasibility/testing review PASS。
实现完成条件必须等用户批准后另行满足,不由本执行版写入自动成立。