Files
junhong_cmp_fiber/docs/feature-504-multi-view-audit-center/跨视角调查与前端导航契约.md
break 88cc5e96ec
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 8m32s
暂存
2026-08-06 09:35:00 +08:00

15 KiB
Raw Blame History

跨视角调查与前端导航契约

本文对应 build-multi-view-audit-center 任务 9.5,冻结 request、correlation、资金和风险调查接口以及现有业务页面进入审计中心的第一跳。所有字段路径均位于统一响应的 response.data 下;列表字段位于 items[]。本文只定义前端调用契约,不包含前端页面实现。

跨视角只读接口

视角 接口 入参来源 响应重点
请求链路 GET /api/admin/audit/requests/{request_id}/timeline 审计或 Integration 节点的 investigation_refs.request_id,或开发人员从 Access Log 粘贴 request_idaccess_log_lookup_request_idnodes[]
业务链路 GET /api/admin/audit/correlations/{correlation_id}/timeline 审计、Integration、Outbox、任务或业务详情中的稳定 correlation correlation_idnodes[]
资金时间线 GET /api/admin/audit/finance/timeline 业务页面稳定 ID、调查节点引用或调查人员输入 分页 items[]、事实来源、金额权威、investigation_refs
风险总览 GET /api/admin/audit/risks/overview 调查人员选择的 RFC3339 时间范围及可选筛选,最长 31 天 信号、风险、结果、动作、来源和趋势
风险明细 GET /api/admin/audit/risks/events 风险总览分桶携带相同筛选,或调查人员输入 分页风险事件及 investigation_refs

以上接口仅允许超级管理员和平台账号访问,全部为 GET。认证身份只来自认证上下文不提供导出、修改、删除、风险处置、自动封禁、重试、补偿或恢复能力。

资产和组织页面逐行导航

源页面 前置接口 response.data 稳定字段 入口名称与可见条件 目标接口与参数映射 降级行为
卡列表 GET /api/admin/iot-cards/standalone items[].id/iccid/virtual_no/shop_id/device_virtual_no/authorized_enterprise_id 平台显示“审计记录”,要求 id 非零;代理显示“活动记录”,要求 iccid 非空;企业不从此列表进入 平台:/audit/resources/iot_card/{id}/timeline;代理:/agent/resource-activities/iot_card/{iccid} 缺少对应 ID/ICCID 时隐藏;企业改从企业卡列表进入
设备列表 GET /api/admin/devices items[].id/virtual_no/imei/sn/shop_id/bound_card_count/authorized_enterprise_id 平台要求 id;代理要求 virtual_no;企业不从此列表进入 平台:/audit/resources/device/{id}/timeline;代理:/agent/resource-activities/device/{virtual_no} 缺少字段时隐藏;企业改从企业设备列表进入
设备卡槽 GET /api/admin/devices/{virtual_no}/cards bindings[].id/iot_card_id/iccid/slot_position/is_current 平台可分别查看卡和绑定审计,要求相应 ID代理可查看卡活动要求 ICCID企业仅在设备和卡均有效授权时显示卡活动 平台卡:iot_card/{iot_card_id};平台绑定:device_sim_binding/{bindings[].id};代理/企业卡:iot_card/{iccid} 的主体活动接口 不用绑定 ID 证明授权;设备时间线继续使用上层设备 ID/VirtualNo
统一资产详情 GET /api/admin/assets/resolve/{identifier} asset_type/asset_id/identifier/virtual_no/iccid/bound_device_id/cards[].card_id/exchange_trace[].asset_id/can_view 平台在 asset_id 存在时显示“审计记录”;代理在卡 ICCID 或设备 VirtualNo 存在时显示“活动记录”;企业不显示 平台:card→iot_card/{asset_id}device→device/{asset_id};代理:卡用 iot_card/{iccid}、设备用 device/{virtual_no} 缺稳定字段时隐藏;换货轨迹仅 can_view=true 且资产 ID 存在时跳转;企业不得回退调用 resolve
资产分配列表/详情 GET /api/admin/asset-allocation-records[/{id}] items[].id/allocation_no/asset_type/asset_id/asset_identifier/from_owner_type/from_owner_id/to_owner_type/to_owner_id/related_device_id;详情另有 related_card_ids[] 平台要求记录或资产 ID代理要求 allocation_no 且当前关联资产或店铺仍在范围内;企业无独立入口 平台:asset_allocation_record/{id}{asset_type}/{asset_id};代理:/agent/resource-activities/asset_allocation_record/{allocation_no} 后端独立复核分配归属;不能因可打开旧详情就视为有权;企业从已授权资产活动查看结论
换货列表/详情 GET /api/admin/exchanges[/{id}] items[].id/exchange_no/old_asset_type/old_asset_id/new_asset_type/new_asset_id/shop_id/submitter_id 平台要求换货或资产 ID代理要求 exchange_no 且换货店铺仍在范围内;企业无独立入口 平台:exchange_order/{id},旧新资产分别使用响应类型和 ID代理/agent/resource-activities/exchange_order/{exchange_no} 旧新资产仅在各自仍可管理时开放;企业从有效授权资产活动查看结论
店铺列表/详情 GET /api/admin/shops[/{id}] items[].id/shop_name/shop_code/parent_id/business_owner_account_id 或详情同名字段 平台要求 id;代理要求 shop_code 且为自己或下级店铺;企业不显示 平台:/audit/resources/shop/{id}/timeline;代理:/agent/resource-activities/shop/{shop_code} 缺字段或越权时隐藏/显示不可用,不搜索平台审计
企业列表 GET /api/admin/enterprises items[].id/enterprise_name/enterprise_code/owner_shop_id 平台要求 id;代理要求 enterprise_code 且 owner shop 在范围内;企业自身不显示 平台:enterprise/{id};代理:/agent/resource-activities/enterprise/{enterprise_code} 当前没有企业详情接口,前端不得假设存在;企业 ID 不作为主体活动路径参数
企业卡列表 GET /api/admin/enterprises/{id}/cards items[].id/iccid/virtual_no/device_id 平台要求 id;企业要求 iccid 且当前授权有效;代理不从此列表进入 平台:iot_card/{id};企业:/enterprise/resource-activities/iot_card/{iccid} 路由中的企业 ID 不作为授权证明;后端始终使用认证上下文复核
企业设备列表 GET /api/admin/enterprises/{id}/devices items[].device_id/virtual_no 平台要求 device_id;企业要求 virtual_no 且当前授权有效;代理不从此列表进入 平台:device/{device_id};企业:/enterprise/resource-activities/device/{virtual_no} 字段为空或授权撤销时隐藏/显示活动不可用,不回退平台接口

账号、交易和资金页面逐行导航

源页面 前置接口 response.data 稳定字段 入口名称与可见条件 目标接口与参数映射 降级行为
账号列表/详情 GET /api/admin/accounts[/{id}] 列表 items[].id;详情 id 平台在 ID 非零时显示“审计记录” /audit/resources/account/{id}/timeline 缺 ID 时隐藏,不按用户名搜索
店铺列表/详情 GET /api/admin/shops[/{id}] 列表 items[].id;详情 id ID 非零时显示“审计记录”和“资金链路” 审计:shop/{id};资金:/audit/finance/timeline?shop_id={id} 缺 ID 时两个入口均隐藏
企业列表 GET /api/admin/enterprises items[].id ID 非零时显示“审计记录” /audit/resources/enterprise/{id}/timeline 不假设存在企业详情接口
订单列表/详情 GET /api/admin/orders[/{id}] items[].id/order_no 或详情 id/order_no ID 非零时显示“审计记录”和“资金链路” 审计:order/{id};资金:/audit/finance/timeline?order_id={id} 不要求前端补 payment/refund ID缺 ID 时隐藏
退款列表/详情 GET /api/admin/refunds[/{id}] items[].id/refund_no/order_id/approval_instance_id 或详情同名字段 ID 非零时显示审计和资金入口;审批 ID 非零时显示“审批审计” 审计:refund/{id};资金:finance/timeline?refund_id={id};审批:approval_instance/{approval_instance_id} 缺审批 ID 只隐藏审批入口,不解析退款编号猜测
代理充值列表/详情 GET /api/admin/agent-recharges[/{id}] items[].id/recharge_no/shop_id/agent_wallet_id/approval_instance_id 或详情同名字段 ID 非零时显示审计和资金入口;审批 ID 非零时显示审批审计 审计:agent_recharge/{id};资金:finance/timeline?recharge_id={id} payment_no 由服务端关联,不要求前端补猜
代理在线充值结果 POST /api/admin/agent-recharges recharge_id/recharge_no/payment_no recharge_id 非零时显示“资金链路” finance/timeline?recharge_id={recharge_id};可附加 payment_no 精确筛选 payment_no 不直接构造 Integration 详情;缺 recharge ID 时隐藏
资产钱包 GET /api/admin/assets/{identifier}/wallet wallet_id/resource_type/resource_id wallet_id 非零时显示“资金链路”;资源类型和 ID 齐全时显示“资产审计” 资金:finance/timeline?wallet_id={wallet_id};审计:resources/{resource_type}/{resource_id}/timeline 两个入口独立判断;缺某组字段只隐藏对应入口
店铺资金概况 GET /api/admin/shops/fund-summary items[].shop_id shop_id 非零时显示行内“资金链路” finance/timeline?shop_id={shop_id} 不要求该接口未返回的 agent wallet ID
店铺主钱包流水 GET /api/admin/shops/{shop_id}/main-wallet/transactions path shop_iditems[].id/asset_type/asset_id/asset_identifier 始终可按合法 path 显示资金入口;资产类型和 ID 齐全时显示资产审计 资金:finance/timeline?shop_id={shop_id};审计:resources/{asset_type}/{asset_id}/timeline 缺资产 ID 仍保留店铺资金入口,不按资产编号猜测
资产钱包流水 GET /api/admin/assets/{identifier}/wallet/transactions 上层钱包接口 wallet_iditems[].id/reference_type/reference_no 上层 wallet_id 非零时显示“资金链路” finance/timeline?wallet_id={wallet_id} reference_type/reference_no 仅展示;需后端节点明确返回资源引用后才能继续跳转

调查节点逐行跳转

investigation_refs 字段 入口名称 可见条件 目标接口与参数 降级行为
event_id “事件详情” 非空 GET /api/admin/audit/events/{event_id} 空值隐藏
actor_ref.kind/id “查看操作者行为” kind 和 id 均非空 GET /api/admin/audit/actors/{kind}/{id}/events 任一缺失即隐藏,不用当前账号资料补齐
resource_refs[] “查看资源审计” resource_type/resource_id 均非空 GET /api/admin/audit/resources/{resource_type}/{resource_id}/timeline 只有 Key 时先精确搜索;零或多命中不自动选择
request_id “查看请求链路” 非空 GET /api/admin/audit/requests/{request_id}/timeline 空值隐藏,不扫描 Access Log 猜测
correlation_id “查看业务链路” 非空 GET /api/admin/audit/correlations/{correlation_id}/timeline 空值隐藏,不按相近时间拼链路
integration_refs[].integration_id “查看外部交互” 非空 GET /api/admin/audit/integrations/{integration_id} 空值隐藏,不使用数据库主键或相似资源猜测

actor_ref.kind 第一阶段只使用 account/openapi/system_task/scheduled_job/external_system。代理和企业活动响应不得包含 investigation_refs

六条完整调用链

资产详情

  1. 调用 GET /api/admin/assets/resolve/{identifier}
  2. 平台读取 data.asset_type/asset_id:卡将 card 转为 iot_card,调用 GET /api/admin/audit/resources/iot_card/{asset_id}/timeline?page=1&page_size=20;设备调用 .../device/{asset_id}/timeline
  3. 代理读取 data.icciddata.virtual_no,调用对应 /agent/resource-activities/...
  4. 字段缺失时隐藏入口;企业不调用 resolve也不回退平台接口。

订单

  1. 调用 GET /api/admin/orders/{id},读取 data.id
  2. “审计记录”调用 GET /api/admin/audit/resources/order/{id}/timeline
  3. “资金链路”调用 GET /api/admin/audit/finance/timeline?order_id={id}&page=1&page_size=20
  4. Payment、Refund、钱包等关联由服务端解析前端不补猜。

退款

  1. 调用 GET /api/admin/refunds/{id},读取 data.id 和可选 data.approval_instance_id
  2. 审计调用 resources/refund/{id}/timeline,资金调用 finance/timeline?refund_id={id}
  3. 审批实例 ID 非零时再调用 resources/approval_instance/{approval_instance_id}/timeline
  4. 审批字段缺失只隐藏审批入口,不影响退款审计与资金链路。

钱包

  1. 调用 GET /api/admin/assets/{identifier}/wallet,读取 data.wallet_id/resource_type/resource_id
  2. “资金链路”调用 finance/timeline?wallet_id={wallet_id}
  3. “资产审计”调用 resources/{resource_type}/{resource_id}/timeline
  4. 两组稳定字段分别判断,不使用交易备注或 reference 编号前缀推断资源。

通知

  1. 点击通知后先调用 GET /api/admin/notifications/{id}/target
  2. 仅当 data.available=true 时展示跳转。
  3. data.target_type=integration_logdata.target_key 非空时,将 target key 原样作为 integration_id 调用 GET /api/admin/audit/integrations/{target_key}
  4. 其他 target type 先进入对应业务详情,再按本文业务页面矩阵进入审计;不可用时只展示通知正文。

风险节点

  1. 调用 GET /api/admin/audit/risks/overview?created_from={from}&created_to={to}
  2. 点击风险、结果、动作或来源分桶时,将相同时间范围和对应稳定编码带入 GET /api/admin/audit/risks/events
  3. 从明细 items[].investigation_refs 直接进入事件、操作者、资源、request、correlation 或 Integration 视角。
  4. 缺少的引用入口隐藏;风险中心不提供处置、封禁或恢复按钮。

统一降级与事实边界

  • 缺少目标接口必需的稳定 ID 或 identifier 时隐藏入口,不按名称、中文描述、时间或编号前缀猜测。
  • 平台只有 Registry Key 时先调用精确资源搜索;零命中或多命中停留在搜索结果。
  • 已删除资源只要调查节点仍有稳定资源类型和 ID就可查看事件快照时间线。
  • 代理或企业遇到越权、授权撤销或资源不存在时统一显示“活动不可用”,不回退平台调查、资源搜索或旧 operation log。
  • request/correlation 时间线的 record_source 保留 Audit Event、Integration Log、Outbox、Asynq 摘要和 Domain Ledger 引用的事实边界Outbox 投递成功不等于业务成功。
  • 资金金额和余额以钱包流水及对应业务表为权威Audit Event 仅用于解释谁做了什么,不用于资金重算。
  • 旧 operation log 仅由平台独立历史入口访问,不拼接到新 /api/admin/audit/*