暂存
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 8m32s

This commit is contained in:
2026-08-06 09:35:00 +08:00
parent 8659dfc658
commit 88cc5e96ec
75 changed files with 6520 additions and 513 deletions

View File

@@ -130,6 +130,82 @@ components:
user_agent:
type: string
type: object
AuditFinanceAmountAuthority:
properties:
authoritative:
type: boolean
conflict_rule:
type: string
field:
type: string
table:
type: string
type: object
AuditFinanceTimelineNode:
properties:
amount:
nullable: true
type: integer
amount_authority:
$ref: '#/components/schemas/AuditFinanceAmountAuthority'
balance_after:
nullable: true
type: integer
balance_before:
nullable: true
type: integer
code:
type: string
currency:
type: string
facts:
additionalProperties: {}
nullable: true
type: object
investigation_refs:
$ref: '#/components/schemas/AuditInvestigationRefs'
node_id:
type: string
occurred_at:
format: date-time
type: string
record_source:
type: string
result:
type: string
result_name:
type: string
shop_id:
minimum: 0
nullable: true
type: integer
title:
type: string
wallet:
$ref: '#/components/schemas/AuditFinanceWalletRef'
type: object
AuditFinanceTimelinePage:
properties:
items:
items:
$ref: '#/components/schemas/AuditFinanceTimelineNode'
nullable: true
type: array
page:
type: integer
page_size:
type: integer
total:
type: integer
type: object
AuditFinanceWalletRef:
properties:
resource_type:
type: string
wallet_id:
minimum: 0
type: integer
type: object
AuditIntegrationRef:
properties:
integration_id:
@@ -171,6 +247,76 @@ components:
resource_type:
type: string
type: object
AuditLinkTimeline:
properties:
access_log_lookup_request_id:
nullable: true
type: string
correlation_id:
nullable: true
type: string
nodes:
items:
$ref: '#/components/schemas/AuditLinkTimelineNode'
nullable: true
type: array
request_id:
nullable: true
type: string
type: object
AuditLinkTimelineNode:
properties:
code:
type: string
correlation_id:
nullable: true
type: string
fidelity:
$ref: '#/components/schemas/AuditLinkageFidelity'
investigation_refs:
$ref: '#/components/schemas/AuditInvestigationRefs'
node_id:
type: string
occurred_at:
format: date-time
type: string
parent_event_id:
nullable: true
type: string
record_source:
type: string
reference_only:
type: boolean
request_id:
nullable: true
type: string
resources:
items:
$ref: '#/components/schemas/AuditInvestigationResourceRef'
nullable: true
type: array
result:
type: string
result_name:
type: string
summary:
type: string
title:
type: string
type: object
AuditLinkageFidelity:
properties:
correlation_available:
type: boolean
direct_audit_link_available:
type: boolean
parent_event_available:
type: boolean
request_available:
type: boolean
stable_resource_available:
type: boolean
type: object
AuditResourceCandidate:
properties:
display_name:
@@ -243,6 +389,88 @@ components:
subject_visibility:
type: string
type: object
AuditRiskEventPage:
properties:
items:
items:
$ref: '#/components/schemas/AuditEventView'
nullable: true
type: array
page:
type: integer
page_size:
type: integer
total:
type: integer
type: object
AuditRiskNamedCount:
properties:
code:
type: string
count:
type: integer
name:
type: string
type: object
AuditRiskOverview:
properties:
actions:
items:
$ref: '#/components/schemas/AuditRiskNamedCount'
nullable: true
type: array
bucket:
type: string
results:
items:
$ref: '#/components/schemas/AuditRiskNamedCount'
nullable: true
type: array
risks:
items:
$ref: '#/components/schemas/AuditRiskNamedCount'
nullable: true
type: array
signals:
items:
$ref: '#/components/schemas/AuditRiskNamedCount'
nullable: true
type: array
sources:
items:
$ref: '#/components/schemas/AuditRiskNamedCount'
nullable: true
type: array
total:
type: integer
trend:
items:
$ref: '#/components/schemas/AuditRiskTrendPoint'
nullable: true
type: array
type: object
AuditRiskTrendPoint:
properties:
bucket_at:
format: date-time
type: string
denied:
type: integer
failed:
type: integer
finance:
type: integer
high_risk:
type: integer
partial:
type: integer
security:
type: integer
total:
type: integer
unknown:
type: integer
type: object
AuditSubjectActivity:
properties:
action_code:
@@ -1594,6 +1822,10 @@ components:
reduction_pct:
description: 展示增幅比例,公式为(real_total_mb / virtual_total_mb) - 1
type: number
renewal_price:
description: 当前主套餐续费价格(分,按当前销售渠道的生效零售价计算;无主套餐或当前渠道不可续费时为 null
nullable: true
type: integer
sn:
description: 设备序列号
type: string
@@ -15253,6 +15485,73 @@ paths:
summary: 查询操作者行为时间线
tags:
- 审计调查
/api/admin/audit/correlations/{correlation_id}/timeline:
get:
description: correlation_id 来自审计、外部集成、可靠事件或业务详情的稳定引用。相同 correlation 只说明属于同一业务链路,不用于猜测技术重试。
parameters:
- description: 跨请求、异步任务和外部交互的稳定业务链路ID
in: path
name: correlation_id
required: true
schema:
description: 跨请求、异步任务和外部交互的稳定业务链路ID
type: string
responses:
"200":
content:
application/json:
schema:
properties:
code:
description: 响应码
example: 0
type: integer
data:
$ref: '#/components/schemas/AuditLinkTimeline'
msg:
description: 响应消息
example: success
type: string
timestamp:
description: 时间戳
format: date-time
type: string
required:
- code
- msg
- data
- timestamp
type: object
description: 成功
"400":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: 请求参数错误
"401":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: 未认证或认证已过期
"403":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: 无权访问
"500":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: 服务器内部错误
security:
- BearerAuth: []
summary: 查询业务关联时间线
tags:
- 审计调查
/api/admin/audit/events:
get:
description: 筛选值来自调查人员输入或其他调查节点的稳定引用身份范围只读取认证上下文。固定按发生时间和事件ID倒序不提供导出、修改或删除。
@@ -15491,6 +15790,190 @@ paths:
summary: 查询审计事件详情
tags:
- 审计调查
/api/admin/audit/finance/timeline:
get:
description: 可使用店铺、钱包、订单、支付、退款、充值、审批、交易号、操作者、时间或 correlation 中任一稳定条件进入;关联事实由服务端解析,金额以钱包流水及对应业务表为权威。
parameters:
- description: 店铺ID
in: query
name: shop_id
schema:
description: 店铺ID
minimum: 0
type: integer
- description: 代理或资产钱包ID
in: query
name: wallet_id
schema:
description: 代理或资产钱包ID
minimum: 0
type: integer
- description: 订单ID
in: query
name: order_id
schema:
description: 订单ID
minimum: 0
type: integer
- description: 订单编号
in: query
name: order_no
schema:
description: 订单编号
type: string
- description: 支付记录ID
in: query
name: payment_id
schema:
description: 支付记录ID
minimum: 0
type: integer
- description: 支付单号
in: query
name: payment_no
schema:
description: 支付单号
type: string
- description: 退款单ID
in: query
name: refund_id
schema:
description: 退款单ID
minimum: 0
type: integer
- description: 退款单号
in: query
name: refund_no
schema:
description: 退款单号
type: string
- description: 代理充值或个人资产充值ID
in: query
name: recharge_id
schema:
description: 代理充值或个人资产充值ID
minimum: 0
type: integer
- description: 充值单号
in: query
name: recharge_no
schema:
description: 充值单号
type: string
- description: 审批实例ID
in: query
name: approval_instance_id
schema:
description: 审批实例ID
minimum: 0
type: integer
- description: 第三方交易号
in: query
name: third_party_trade_no
schema:
description: 第三方交易号
type: string
- description: 操作者类型与actor_id同时提供
in: query
name: actor_kind
schema:
description: 操作者类型与actor_id同时提供
type: string
- description: 操作者稳定ID与actor_kind同时提供
in: query
name: actor_id
schema:
description: 操作者稳定ID与actor_kind同时提供
type: string
- description: 跨步骤业务链路ID
in: query
name: correlation_id
schema:
description: 跨步骤业务链路ID
type: string
- description: 开始时间RFC3339含时区
in: query
name: created_from
schema:
description: 开始时间RFC3339含时区
type: string
- description: 结束时间RFC3339含时区不包含该时刻
in: query
name: created_to
schema:
description: 结束时间RFC3339含时区不包含该时刻
type: string
- description: 页码默认1
in: query
name: page
schema:
description: 页码默认1
minimum: 1
type: integer
- description: 每页数量默认20最大100
in: query
name: page_size
schema:
description: 每页数量默认20最大100
maximum: 100
minimum: 1
type: integer
responses:
"200":
content:
application/json:
schema:
properties:
code:
description: 响应码
example: 0
type: integer
data:
$ref: '#/components/schemas/AuditFinanceTimelinePage'
msg:
description: 响应消息
example: success
type: string
timestamp:
description: 时间戳
format: date-time
type: string
required:
- code
- msg
- data
- timestamp
type: object
description: 成功
"400":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: 请求参数错误
"401":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: 未认证或认证已过期
"403":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: 无权访问
"500":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: 服务器内部错误
security:
- BearerAuth: []
summary: 查询资金调查时间线
tags:
- 审计调查
/api/admin/audit/integrations:
get:
description: 组合筛选来自调查输入或关联视角稳定引用固定按创建时间和记录ID倒序分页不提供任意摘要搜索。
@@ -15951,6 +16434,73 @@ paths:
summary: 查询外部集成交互总览
tags:
- 审计调查
/api/admin/audit/requests/{request_id}/timeline:
get:
description: request_id 来自审计或外部集成节点,也可由开发人员从 Access Log 粘贴。响应组合审计事件、外部交互、可靠事件和业务账本引用,但不扫描 Access Log 文件。
parameters:
- description: HTTP请求关联ID来自审计或外部集成节点也可从Access Log粘贴
in: path
name: request_id
required: true
schema:
description: HTTP请求关联ID来自审计或外部集成节点也可从Access Log粘贴
type: string
responses:
"200":
content:
application/json:
schema:
properties:
code:
description: 响应码
example: 0
type: integer
data:
$ref: '#/components/schemas/AuditLinkTimeline'
msg:
description: 响应消息
example: success
type: string
timestamp:
description: 时间戳
format: date-time
type: string
required:
- code
- msg
- data
- timestamp
type: object
description: 成功
"400":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: 请求参数错误
"401":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: 未认证或认证已过期
"403":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: 无权访问
"500":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: 服务器内部错误
security:
- BearerAuth: []
summary: 查询请求关联时间线
tags:
- 审计调查
/api/admin/audit/resources/{resource_type}/{resource_id}/timeline:
get:
description: resource_type/resource_id 必须来自业务页面稳定字段、资源搜索结果或 investigation_refs。事件在资源作为 primary、affected 或 reference 时均会返回。
@@ -16153,6 +16703,217 @@ paths:
summary: 精确搜索注册资源
tags:
- 审计调查
/api/admin/audit/risks/events:
get:
description: 筛选条件来自风险总览分桶或调查人员输入,明细返回统一 investigation_refs可继续进入事件、资源、操作者和 correlation 视角;不提供处置或封禁能力。
parameters:
- description: 开始时间RFC3339含时区必填
in: query
name: created_from
required: true
schema:
description: 开始时间RFC3339含时区必填
type: string
- description: 结束时间RFC3339含时区不包含该时刻最长31天必填
in: query
name: created_to
required: true
schema:
description: 结束时间RFC3339含时区不包含该时刻最长31天必填
type: string
- description: 风险等级 (low:低, normal:普通, high:高, critical:严重)
in: query
name: risk
schema:
description: 风险等级 (low:低, normal:普通, high:高, critical:严重)
type: string
- description: 结果 (success:成功, failed:失败, denied:拒绝, partial:部分成功, unknown:未知)
in: query
name: result
schema:
description: 结果 (success:成功, failed:失败, denied:拒绝, partial:部分成功, unknown:未知)
type: string
- description: 稳定动作编码
in: query
name: action
schema:
description: 稳定动作编码
type: string
- description: 来源 (admin_api:后台管理API, personal_api:个人客户API, openapi:代理OpenAPI, worker:异步Worker, scheduler:计划任务, callback:外部系统回调)
in: query
name: source
schema:
description: 来源 (admin_api:后台管理API, personal_api:个人客户API, openapi:代理OpenAPI, worker:异步Worker, scheduler:计划任务, callback:外部系统回调)
type: string
- description: 页码默认1
in: query
name: page
schema:
description: 页码默认1
minimum: 1
type: integer
- description: 每页数量默认20最大100
in: query
name: page_size
schema:
description: 每页数量默认20最大100
maximum: 100
minimum: 1
type: integer
responses:
"200":
content:
application/json:
schema:
properties:
code:
description: 响应码
example: 0
type: integer
data:
$ref: '#/components/schemas/AuditRiskEventPage'
msg:
description: 响应消息
example: success
type: string
timestamp:
description: 时间戳
format: date-time
type: string
required:
- code
- msg
- data
- timestamp
type: object
description: 成功
"400":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: 请求参数错误
"401":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: 未认证或认证已过期
"403":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: 无权访问
"500":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: 服务器内部错误
security:
- BearerAuth: []
summary: 查询风险事件明细
tags:
- 审计调查
/api/admin/audit/risks/overview:
get:
description: 必须提供最长31天的时间范围只聚合高风险、资金、安全、失败、拒绝、部分成功和结果未知事件普通低风险成功事件不计入。
parameters:
- description: 开始时间RFC3339含时区必填
in: query
name: created_from
required: true
schema:
description: 开始时间RFC3339含时区必填
type: string
- description: 结束时间RFC3339含时区不包含该时刻最长31天必填
in: query
name: created_to
required: true
schema:
description: 结束时间RFC3339含时区不包含该时刻最长31天必填
type: string
- description: 风险等级 (low:低, normal:普通, high:高, critical:严重)
in: query
name: risk
schema:
description: 风险等级 (low:低, normal:普通, high:高, critical:严重)
type: string
- description: 结果 (success:成功, failed:失败, denied:拒绝, partial:部分成功, unknown:未知)
in: query
name: result
schema:
description: 结果 (success:成功, failed:失败, denied:拒绝, partial:部分成功, unknown:未知)
type: string
- description: 稳定动作编码
in: query
name: action
schema:
description: 稳定动作编码
type: string
- description: 来源 (admin_api:后台管理API, personal_api:个人客户API, openapi:代理OpenAPI, worker:异步Worker, scheduler:计划任务, callback:外部系统回调)
in: query
name: source
schema:
description: 来源 (admin_api:后台管理API, personal_api:个人客户API, openapi:代理OpenAPI, worker:异步Worker, scheduler:计划任务, callback:外部系统回调)
type: string
responses:
"200":
content:
application/json:
schema:
properties:
code:
description: 响应码
example: 0
type: integer
data:
$ref: '#/components/schemas/AuditRiskOverview'
msg:
description: 响应消息
example: success
type: string
timestamp:
description: 时间戳
format: date-time
type: string
required:
- code
- msg
- data
- timestamp
type: object
description: 成功
"400":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: 请求参数错误
"401":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: 未认证或认证已过期
"403":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: 无权访问
"500":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: 服务器内部错误
security:
- BearerAuth: []
summary: 查询风险调查总览
tags:
- 审计调查
/api/admin/authorizations:
get:
parameters:

View File

@@ -11,6 +11,10 @@
| 操作者 | `GET /api/admin/audit/actors/{kind}/{id}/events` | `investigation_refs.actor_ref` 或平台账号选择器 |
| 资源搜索 | `GET /api/admin/audit/resources/search` | 调查人员选择类型并输入精确业务标识 |
| 资源时间线 | `GET /api/admin/audit/resources/{resource_type}/{resource_id}/timeline` | 业务响应稳定 ID、资源搜索结果或 `investigation_refs.resource_refs[]` |
| 请求链路 | `GET /api/admin/audit/requests/{request_id}/timeline` | 节点 `request_id` 或开发人员从 Access Log 粘贴 |
| 业务链路 | `GET /api/admin/audit/correlations/{correlation_id}/timeline` | 节点或业务详情中的稳定 `correlation_id` |
| 资金时间线 | `GET /api/admin/audit/finance/timeline` | 店铺、钱包、订单、支付、退款、充值、审批、交易号、操作者、时间或 correlation |
| 风险总览/明细 | `GET /api/admin/audit/risks/overview``GET /api/admin/audit/risks/events` | 调查时间范围及风险分桶稳定筛选 |
认证身份和数据范围只来自认证上下文,不接受 query/path/body 伪造。接口仅允许超级管理员和平台账号访问,全部为 GET不提供导出、修改、删除、恢复或处置能力。
@@ -43,7 +47,7 @@
| 店铺主钱包流水 | path `shop_id`、资产类型与 ID | 资金视角使用 `shop_id`;资产 ID 存在时使用对应资源时间线 |
| 资产钱包流水 | 上层 `wallet_id` | 资金视角使用 `wallet_id`;不解析业务编号前缀猜测资源 |
资金视角将在后续任务交付;当前文档只冻结其第一跳参数,缺失的支付、退款、钱包等关联由服务端 Query 解析。
资金视角已交付;缺失的支付、退款、钱包等关联由服务端 Query 解析。完整逐页面映射和调用链见[跨视角调查与前端导航契约](跨视角调查与前端导航契约.md)。
## 统一调查引用

View File

@@ -0,0 +1,113 @@
# 跨视角调查与前端导航契约
本文对应 `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_id``access_log_lookup_request_id``nodes[]` |
| 业务链路 | `GET /api/admin/audit/correlations/{correlation_id}/timeline` | 审计、Integration、Outbox、任务或业务详情中的稳定 correlation | `correlation_id``nodes[]` |
| 资金时间线 | `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_id``items[].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_id``items[].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.iccid``data.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_log``data.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/*`