15 KiB
ADDED Requirements
Requirement: 平台审计调查接口必须使用平台身份边界
系统 MUST 仅允许超级管理员和平台账号访问 /api/admin/audit 下的内部审计调查接口。第一阶段 MUST NOT 要求细粒度审计权限码,也 MUST NOT 对平台账号增加店铺或企业数据范围过滤;代理、企业和个人客户 MUST 被后端拒绝,不能仅依赖前端隐藏页面。
Scenario: 平台账号查看全局审计
- WHEN 已认证平台账号请求内部审计接口
- THEN 系统返回全部数据范围内符合筛选条件的审计数据
- AND 不要求尚未稳定的细粒度审计权限码
Scenario: 非平台身份直接调用内部接口
- WHEN 代理、企业或个人客户绕过前端直接请求
/api/admin/audit/events - THEN 系统返回统一的禁止访问错误
- AND 不泄露是否存在匹配的审计事件
Requirement: 系统必须提供全局事件列表和事件详情
系统 SHALL 提供 GET /api/admin/audit/events 和 GET /api/admin/audit/events/{event_id}。列表 MUST 支持 created_from、created_to、action、category、actor_kind、actor_id、source、result、risk、scope_type、scope_id、resource_type、resource_id、resource_key、request_id、correlation_id、page、page_size 组合筛选;详情 MUST 返回事件上下文、操作者快照、结果、链路以及全部资源关系、身份快照和各资源前后变化。
Scenario: 组合筛选全局事件
- WHEN 平台账号按操作者、失败结果、资金类别和时间范围查询事件
- THEN 系统只返回同时满足条件的事件
- AND 每项包含稳定编码、中文名称、主要资源、结果和发生时间
Scenario: 查看多资源事件详情
- WHEN 平台账号查看一次换货审计事件
- THEN 系统返回换货单、旧卡/设备、新卡/设备、绑定、店铺及实际涉及的订单、钱包和套餐资源
- AND 每个资源分别返回 role、身份快照及自身 before/after
Requirement: 系统必须提供操作者行为视角
系统 SHALL 提供 GET /api/admin/audit/actors/{kind}/{id}/events,按时间倒序展示指定人工账号、OpenAPI 账号、系统任务或外部系统的操作。查询 MUST 支持 action、result、risk、resource 和时间过滤,并使用事件中的操作者快照解释历史。
Scenario: 调查平台账号行为
- WHEN 调查人员查询某平台账号最近七天的操作
- THEN 系统返回该操作者的成功、失败、拒绝和部分成功事件
- AND 账号后来改名或删除不改变历史操作者名称快照
Scenario: 调查系统自动状态变化
- WHEN 调查人员查询
system_task操作者类型 - THEN 系统返回 Worker 和 Scheduler 引发的内部状态变化
- AND 不将系统操作伪造成平台人工操作
Requirement: 系统必须提供通用资源搜索和资源时间线
系统 SHALL 提供 GET /api/admin/audit/resources/search 和 GET /api/admin/audit/resources/{type}/{id}/timeline。资源搜索 MUST 只使用 Resource Registry 已注册的精确标识或有索引关键词;资源时间线 MUST 通过 Event Resource 通用生成,不要求为每个领域新建审计表或时间线接口。
Scenario: 通过卡标识打开时间线
- WHEN 平台账号使用 ICCID 或 VirtualNo 搜索 IoT 卡并选择结果
- THEN 系统返回资源候选及稳定资源 ID
- AND 时间线展示该卡作为 primary、affected 或 reference 参与的事件
Scenario: 查询设备某张绑定卡的轨迹
- WHEN 设备入口对其第二卡槽的卡执行操作
- THEN 同一事件出现在设备、卡和必要绑定关系的时间线
- AND 时间线能区分
entry_device、bound_card和卡槽角色
Scenario: 历史资源已经删除或标识改变
- WHEN 当前业务表无法再返回事件发生时的资源名称或标识
- THEN 系统使用 Event Resource 保存的身份快照解释历史
Requirement: 系统必须提供请求和业务关联时间线
系统 SHALL 提供 GET /api/admin/audit/requests/{request_id}/timeline 和 GET /api/admin/audit/correlations/{correlation_id}/timeline。时间线 MUST 组合可关联的 Audit Event、Integration Log、Outbox/任务摘要及 Domain Ledger 引用,并为每个节点返回明确 record_source;系统 MUST NOT 把 Access Log 文件正文或不同事实复制成 Audit Event。
Scenario: 调查一次 HTTP 请求
- WHEN 平台账号通过 request ID 查询链路
- THEN 系统按发生时间返回该请求产生的内部操作、外部交互和可靠事件摘要
- AND 返回用于开发人员检索 Access Log 的 request ID 而不扫描日志文件
Scenario: 调查跨请求退款链路
- WHEN 平台账号通过退款 correlation ID 查询业务链路
- THEN 系统展示申请、审批、外部回调、退款处理、钱包回充、佣金和套餐后处理节点
- AND 每个金额或状态结论标明其 Domain Ledger 来源
Scenario: correlation 不能证明技术重试关系
- WHEN 多条 Integration Log 只有相同 correlation ID 而没有稳定 trigger series
- THEN 业务时间线可展示它们属于同一业务链路
- AND 系统不得将它们标记为同一次外呼的重试序列
Requirement: 系统必须提供资金调查视角
系统 SHALL 提供 GET /api/admin/audit/finance/timeline,支持 shop_id、wallet_id、order_id、order_no、payment_id、payment_no、refund_id、refund_no、recharge_id、recharge_no、approval_instance_id、third_party_trade_no、actor_kind、actor_id、correlation_id、created_from、created_to、page、page_size 组合筛选。该视角 MUST 组合 Audit Event 与钱包流水、订单、支付、退款、充值、佣金和审批等 Domain Ledger,并明确金额权威来自业务流水而非 Audit Event;调用方只提供任一可用稳定业务条件时,Query MUST 在服务端解析关联事实,不得要求前端补齐同一链路全部 ID。
Scenario: 解释钱包余额变化
- WHEN 平台账号按钱包或交易流水查询资金时间线
- THEN 系统返回触发人、业务动作、订单/退款/充值、审批、金额和余额前后值
- AND 金额结论以钱包流水及对应业务表为准
Scenario: 资金事实与审计内容不一致
- WHEN Audit Event 摘要与 Domain Ledger 的金额事实出现差异
- THEN 接口明确标注数据来源并以 Domain Ledger 作为资金权威
- AND 不通过修改历史 Audit Event 掩盖差异
Requirement: 系统必须提供风险和异常视角
系统 SHALL 提供 GET /api/admin/audit/risks/overview 和 GET /api/admin/audit/risks/events,展示高风险、资金、安全、失败、拒绝、部分成功和结果未知事件的数量、趋势与明细。总览 MUST 限定时间范围,明细 MUST 可跳转到事件、资源、操作者和 correlation 视角。
Scenario: 查看失败和拒绝趋势
- WHEN 平台账号查询最近二十四小时风险总览
- THEN 系统按风险、结果、action 和来源返回聚合数量与时间趋势
- AND 不把普通低风险成功事件计入异常数量
Scenario: 从风险事件继续调查
- WHEN 平台账号选择一条高风险资金拒绝事件
- THEN 系统返回稳定事件 ID及其操作者、资源和业务链路跳转信息
Requirement: 查询响应必须稳定、分页且面向前端投影
所有审计查询 SHALL 使用专用 DTO 和统一响应 {code,msg,data,timestamp},不得直接返回 GORM Model。列表 MUST 默认每页 20、最大 100,使用时间与稳定 ID 排序;Query MUST 批量加载资源与业务引用,避免 N+1,并满足 API P95 < 200ms、P99 < 500ms、数据库查询 < 50ms 的目标。
Scenario: 稳定翻页
- WHEN 多条事件具有相同发生时间且调用方连续翻页
- THEN 系统使用发生时间和稳定 ID 作为排序游标或等价稳定排序
- AND 不重复或遗漏事件
Scenario: 查询多资源列表
- WHEN 一页包含多个动作和资源类型
- THEN Query 批量加载 Event Resource 与必要展示信息
- AND 不为每条事件逐一查询操作者、资源或 Domain Ledger
Requirement: 平台调查接口必须明确查询入参来源
平台调查接口的筛选字段 SHALL 来自调查人员输入或上一个视角携带的稳定跳转值;认证用户类型和当前账号 ID MUST 来自认证上下文,不得由 query、path 或 body 指定。事件 ID、资源 ID、actor ID、request ID、correlation ID 和资金业务标识 MUST 使用列表、详情、业务页面或已记录节点提供的稳定值,Query MAY 根据稳定 ID 批量派生中文名称、资源展示信息、关联节点和 Domain Ledger 内容,但 MUST NOT 按时间接近、中文描述或模糊关键词猜测关联。
Scenario: 从事件节点跳转到其他视角
- WHEN 调查人员从事件、资源、操作者、风险或链路节点继续调查
- THEN 前端使用该节点返回的稳定 event、resource、actor、request 或 correlation 标识构造目标接口入参
- AND 后端只校验和查询该稳定标识,不猜测缺失关联
Scenario: 调查人员直接筛选
- WHEN 调查人员在全局、资源搜索、资金或风险视角填写时间、动作、结果、风险或业务标识
- THEN Handler 从受控 query/path 参数读取筛选条件并执行格式、枚举、分页及时间范围校验
- AND 未提供的筛选条件不由后端补猜
Scenario: 身份范围来自认证上下文
- WHEN 任一调用方请求平台调查接口
- THEN Handler 仅从认证上下文取得用户类型和当前账号 ID
- AND 忽略或拒绝调用方伪造的店铺、企业或身份范围参数
Requirement: 业务页面必须具备可执行的审计导航契约
系统 SHALL 为已纳入第一阶段的业务列表和详情冻结“前置接口、response.data 字段、入口可见条件、目标审计接口、参数映射和降级行为”。账号、店铺、企业、卡、设备、设备卡槽、资产详情、分配、换货、订单、退款、代理充值、资产钱包及店铺资金页面 MUST 使用其现有响应中的稳定 ID 或 Registry Key;前端 MUST NOT 解析中文名称、备注或编号前缀推断资源。
Scenario: 平台从卡资产详情查看审计
- WHEN
GET /api/admin/assets/resolve/{identifier}返回asset_type=card、asset_id和iccid - THEN 平台页面使用
resource_type=iot_card与resource_id=asset_id调用GET /api/admin/audit/resources/{resource_type}/{resource_id}/timeline - AND 不使用 ICCID 再搜索一次或把
card直接当成未注册资源类型
Scenario: 平台从订单详情查看资金链路
- WHEN
GET /api/admin/orders/{id}返回订单id,但没有返回全部 Payment、Refund 或 Integration 标识 - THEN 页面调用
GET /api/admin/audit/finance/timeline?order_id={id} - AND Query 在服务端解析关联事实,不要求前端补猜缺失 ID
Scenario: 前置响应缺少稳定引用
- WHEN 业务响应没有目标审计接口需要的稳定 ID 或 Registry Key
- THEN 前端不展示对应入口,后端也不按名称、时间、描述或编号前缀推断
Requirement: 平台调查节点必须返回统一跳转引用
平台事件、资源、操作者、request、correlation、资金、风险及 Integration 关联节点 SHALL 返回统一的 investigation_refs,包含可空 event_id、可空 actor_ref{kind,id}、resource_refs[]{resource_type,resource_id,resource_key,display_name}、可空 request_id、可空 correlation_id 和 integration_refs[]{integration_id}。前端 MUST 仅使用存在的稳定引用导航;代理和企业响应 MUST NOT 复用或暴露该内部结构。
Scenario: 从风险节点继续调查
- WHEN 风险事件节点同时包含 event、actor、resource 和 correlation 引用
- THEN 前端可分别调用事件详情、操作者事件、资源时间线和 correlation 时间线
- AND 每个目标参数直接来自
investigation_refs对应字段
Scenario: 节点缺少关联标识
- WHEN 节点没有 request、correlation 或 Integration 稳定标识
- THEN 前端隐藏对应跳转,不按相近时间或相同资源猜测链路
Scenario: 旧日志不能跳新审计
- WHEN 平台查看独立旧 operation log 入口中的切换前记录
- THEN 页面不为该记录构造新 Audit Event、资源时间线或 correlation 跳转
Requirement: 调查接口必须只读并完整展示已存业务字段
第一阶段所有平台调查接口 MUST 只读,MUST NOT 提供 Audit Event 修改、删除、导出、风险处置、重试、补偿、绑定或恢复操作。平台接口 SHALL 返回审计库中已保存的手机号、IP、ICCID、VirtualNo、金额、交易号和 before/after 等完整业务字段;系统安全凭据及原始第三方敏感正文 MUST 在写入前删除,因此任何查询均不得返回。
Scenario: 平台查看业务敏感字段
- WHEN 平台账号查看资金或资产事件详情
- THEN 系统返回已保存的完整业务金额、资产标识、操作者 IP 和业务前后值
- AND 不执行展示层掩码
Scenario: 请求审计导出或修改
- WHEN 调用方尝试通过审计中心导出、修改或删除审计记录
- THEN 系统不存在对应写接口
Scenario: 系统安全凭据不存在于详情
- WHEN 平台账号查看支付、企微或系统配置相关事件
- THEN 响应不包含密码、Token、Secret、私钥、回调凭据、Authorization、Cookie、签名 URL 或支付密钥
Requirement: 调查接口必须公开在线留存边界
全局、操作者、资源、request、correlation、资金和风险查询 MUST 在 DTO 中返回 retention{online_from, archived_before, timezone}。系统 MUST 只查询 PostgreSQL 在线窗口;显式时间范围早于或跨越 online_from 时 MUST 返回稳定的已归档错误及当前在线边界,不得返回误导性空结果或不完整时间线。第一阶段 MUST NOT 从对象存储补查历史。
Scenario: 业务页面打开资源审计
- WHEN 平台从卡、设备、订单或其他业务详情打开资源时间线且未指定历史时间
- THEN 接口返回当前在线窗口内的事件及 retention 元数据
- AND 页面明确提示早于
online_from的记录已转冷归档、当前不可在线查询
Scenario: 请求上月已归档时间线
- WHEN 调查人员显式指定的时间范围全部早于
online_from - THEN 接口返回稳定的已归档错误和当前在线边界
- AND 不返回成功空列表、不扫描对象存储