- approve only appListSecurityEvents and appGetSecurityEvent at operation level - keep appAcknowledgeSecurityEvent needs_verification - add HTTP+DB completed approval IT and update coverage gates/docs
12 KiB
P1R Account Security Events Completed Approval 审阅版
日期:2026-06-13
结论
推荐 Account 下一批只推进 2 个用户安全事件只读 operation-level completed approval:
account:appListSecurityEvents
account:appGetSecurityEvent
暂不推进 account:appAcknowledgeSecurityEvent。原因是 OpenAPI 当前仍承诺 session_revoked 会联动 session 管理并使相关会话失效,但当前实现返回“未接入 session 管理服务”的 fail-closed 文案。operation-level completed 不能排除单个 action 子路径;在 OpenAPI 或真实 session revoke 未闭合前,把整个 acknowledge operation 标为 completed 会制造 fake completed。
本切片 completed 口径只覆盖:对既有 muse_member_security_event 安全事件事实的当前登录用户可见读取、详情脱敏、latest ack 合并、owner/tenant 隔离、API version 和 read no-write 闭环。
本审阅版只冻结候选范围、证据标准、风险边界和后续执行版要求。不修改 OpenAPI,不修改 scanner,不修改 coverage report,不修改业务实现,不推进任何 operation completed。
flowchart TB
Current["当前 Account<br/>10 completed / 23 needs_verification"] --> Candidate["下一批候选<br/>Security Events read 2 ops"]
Candidate --> Read["list / detail<br/>owner 可见 + 脱敏 + latest ack"]
Candidate --> Exclude["暂缓 acknowledge<br/>session_revoked 合同不闭合"]
Read --> Review["fresh spec/scope review<br/>fresh quality/testing review"]
Exclude --> Keep["继续 needs_verification"]
Review --> Exec["双 PASS 后进入审批点"]
Exec --> Approval{"用户明确批准后才实现"}
Approval -->|"否"| Stay["保持 233/145/88"]
Approval -->|"是"| Target["目标 233/147/86<br/>Account 12 completed / 21 needs_verification"]
当前事实状态
工作区:
/Users/qingse/.config/superpowers/worktrees/oh-my-muse/dev-1.0.0
当前 HEAD:
304f665 test(p1r): 收口 Content Admin RiskAction completed approval 门禁
当前 coverage summary:
total=233
completed=145
needsVerification=88
incomplete=0
genericPersistence=0
ssePlaceholder=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 requiresCommandId=false GET /app-api/muse/account/security-events
appGetSecurityEvent dedicated needs_verification requiresCommandId=false GET /app-api/muse/account/security-events/{eventId}
获批后的目标值:
total=233
completed=147
needsVerification=86
incomplete=0
genericPersistence=0
ssePlaceholder=0
account total=33
completed=12
needsVerification=21
推荐候选
| operation key | Method | Path | 推荐原因 | 必补 completed-grade evidence |
|---|---|---|---|---|
account:appListSecurityEvents |
GET |
/app-api/muse/account/security-events |
读当前登录用户安全事件摘要,支持 severity 筛选和 latest ack 合并,无写入副作用 | MockMvc HTTP + 真实 PostgreSQL _test,覆盖 owner/tenant 隔离、severity filter、分页、latest ack、敏感字段不泄露、missing API version 拒绝、read no-write |
account:appGetSecurityEvent |
GET |
/app-api/muse/account/security-events/{eventId} |
读当前登录用户安全事件详情,服务端按 eventId + accountUserId 查询并脱敏 IP / User-Agent | MockMvc HTTP + 真实 PostgreSQL _test,覆盖 detail 脱敏、跨 owner/跨 tenant/missing 不可见、ack detail 合并、非数字 eventId 404、read no-write |
推荐理由:
- 2 个 operation 都属于 Account 本域
AccountSecurityServiceImpl,不需要调用 New-API、FileService、Market、Content、AI 或 Knowledge 外部 owner。 - App 端 Controller 使用
getLoginUserId(),不接受请求参数覆盖 owner,适合用 HTTP + DB 证明 owner 隔离。 - OpenAPI 的 list/detail 合同与当前实现方向一致:当前账户可见、安全事件详情、敏感值脱敏。
- 读侧需要合并
muse_account_security_event_acklatest ack,但不需要证明 ack 写命令 completed。
不纳入本批的 Account operation
以下 21 个 Account 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
排除原因:
appAcknowledgeSecurityEvent的session_revokedOpenAPI 合同承诺与当前实现 fail-closed 文案不闭合;必须单独处理合同或实现后再审批。- New-API binding、recheck、quota request 和 integration correlation 仍依赖真实 New-API runtime 或外部调用归因闭环。
- FileService / export download 仍缺真实文件交付、下载字节、对象存储和凭证消费端到端 evidence。
- call attribution job 当前 create 路径只创建 queued job 事实,真实归因执行仍由后续 owner/facade 接入;可作为后续独立切片,但不能夹入本批。
- Market purchase / license / publish 仍缺 Market 主流程到 Account projection 的跨 owner 一致性 evidence。
- usage summary / admin usage 仍受
muse_member_usage_record和 attribution source 质量影响,本批不绕过上游事实缺口。
已有实现证据
OpenAPI 合同
OpenAPI 当前包含 2 个本批候选读 operation:
GET /app-api/muse/account/security-events
GET /app-api/muse/account/security-events/{eventId}
本切片不需要修改 docs/api-contracts/account/openapi.yaml。但 OpenAPI 中 acknowledge 的 session_revoked 文案当前是阻塞项,因此本批明确不推进 appAcknowledgeSecurityEvent。
Controller 入口
AppAccountSecurityController 当前链路:
GET /muse/account/security-events
GET /muse/account/security-events/{eventId}
AccountApiVersionGuard.requireVersion(apiVersion)
getLoginUserId()
AccountSecurityService
说明:
- Controller-local mapping 是
/muse/account/...;对外 OpenAPI 路径仍以/app-api/muse/...为准。 - 执行版必须用当前项目既有 app MockMvc / Web 测试上下文证明最终 app API 路径可访问。
list/detail都必须证明缺少X-API-Version时不调用 service。
Service 读链路
AccountSecurityServiceImpl.appListSecurityEvents:
requireUser(accountUserId)。- normalize severity,只允许
info / warning / critical。 MemberSecurityEventMapper.selectPageByAccountUserIdAndSeverity(...)。- 批量读取当前 owner 最新 ack。
- 转换摘要 VO,敏感字段不直接外泄。
AccountSecurityServiceImpl.appGetSecurityEvent:
requireUser(accountUserId)。- 解析 eventId,非数字或空值按 not found 处理。
MemberSecurityEventMapper.selectByIdAndAccountUserId(...)。- 读取当前 owner 最新 ack。
- 转换详情 VO,脱敏 IP / userAgent。
Schema 与测试前置
P1R SQL 当前定义目标事实表:
V2: muse_member_security_event
V11: muse_account_security_event_ack
但 AccountSecurityServiceImpl.requireUser() 会通过 MemberUserMapper.selectById 读取 member_user,而 sql/muse 当前 V1-V21 不创建 member_user。执行版必须明确:HTTP+DB _test 可以在隔离库完成 V1-V21 clean migrate 后创建 test-local member_user auth fixture 表并 seed 登录用户,用于满足认证前置;该 fixture 不计入 P1R Account schema evidence,不能修改 production SQL,也不能替代目标安全事件表/ack 表证据。
执行版必须 fresh 证明:
- V1-V21 clean migrate 成功,且新 HTTP+DB IT 使用当前 live migration baseline。
- 目标表
muse_member_security_event、muse_account_security_event_ack的列、索引、trigger 和 JSONB 字段真实存在。 - test-local
member_userfixture 只在_test库、Flyway migrate 后创建,并在测试内记录为 auth fixture;DDL 至少覆盖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。
风险与取舍
-
appAcknowledgeSecurityEvent暂缓是必须的。- 当前 OpenAPI 对
session_revoked承诺真实 session revoke。 - 当前实现只返回 fail-closed 文案。
- 在合同或实现未闭合前,不能把整个 operation 标为 completed。
- 当前 OpenAPI 对
-
member_user是测试 harness 前置,不是目标业务证据。- 不能 mock
MemberUserMapper来掩盖真实 service 依赖。 - 也不能修改
sql/muse迁移补这个表。 - 允许在隔离
_test库、V1-V21 migrate 后创建 test-local fixture,并明确不计入 P1R schema evidence。 - fixture DDL 必须覆盖真实
MemberUserMapper.selectById会读取的当前实体映射列,不能只建id/nickname等最小列。
- 不能 mock
-
安全事件生产路径不是本批完成条件。
- 已知
AccountExportServiceImpl.insertSensitiveExportEvent会写安全事件 source fact。 - 但本批不证明高敏导出文件交付或所有安全事件来源 completed。
- 已知
-
App HTTP + real DB gate 必须避免假绿。
- 不能只靠 Mockito service/controller tests。
- 必须读取新鲜 Surefire XML,检查 tests>0、failures=0、errors=0、skipped=0。
后续执行版必须包含
- 2 个目标 operation 的审批清单、当前状态和目标状态。
- 保持
needs_verification的 21 个 Account operation 及原因。 - TDD RED:先改 P1R gate 期望,旧 report 必须失败。
- TDD GREEN:只把 2 个
account:*operation 加入 operation-level allowlist,不加accountdomain allowlist。 - 新增
P1rAccountSecurityEventsCompletedApprovalIT,使用 MockMvc HTTP + 真实 PostgreSQL_test。 - App 端登录用户上下文、tenant interceptor、API version、真实 mapper、test-local
member_userauth fixture 的组合方式。 - schema gate:新 HTTP+DB IT 必须执行 V1-V21 clean migrate;V2/V11 安全事件表、ack 表、唯一约束、索引、trigger、JSONB 字段断言;Account 专属
P1rAccountEventsPublishFlywayMigrationIT可继续作为 V20 outbox 证据,但不能替代新 IT 的 V21 baseline。 - runtime matrix:happy、empty page、severity filter、latest ack、detail 脱敏、cross owner、cross tenant、missing、invalid eventId、read no-write。
- P1R mixed gates:至少覆盖 Account、Coverage、Events、AI、Knowledge、Market、Content、Meta。
- XML 防空跑、protected diff、allowed diff 和 rollback 策略。
.agent与docs/memorys留痕要求。
验收标准
本审阅版可以视为完成的条件:
- 文件写入
docs/agent-specs/2026-06-13-P1RAccountSecurityEventsCompletedApproval审阅版.md。 .agent记录 Account Security Events completed approval 审阅版状态。git diff --check通过。- OpenAPI、scanner、coverage report、业务实现、SQL migration 当前无新增 diff。
- fresh spec/scope review PASS。
- fresh quality/feasibility/testing review PASS。
待确认项
- 是否确认 Account 下一批只做这 2 个 security events read operation-level completed approval。
- 是否确认
appAcknowledgeSecurityEvent因session_revoked合同不闭合继续保持needs_verification。 - 是否确认本批不把
account加入 domain-level completed allowlist。 - 是否确认允许 HTTP+DB
_test在隔离_test库内创建 test-localmember_userauth fixture,但不修改 production SQL、不把该 fixture 计入 P1R schema evidence。