42 KiB
审计链路与前端接入指南
本文对应 build-multi-view-audit-center 任务 9.5,作为审计链路和前端接入的单一说明入口。它回答以下问题:链路 ID 从哪里产生、存到哪里、不同入口为什么有的没有 request_id、15 条审计接口如何调用、每个入参与返回字段表示什么,以及前端应在哪些现有业务页面增加入口。
所有接口都使用统一响应 {code,msg,data,timestamp};本文中的返回字段默认位于 response.data,列表项默认位于 response.data.items[]。本文定义调用契约,不包含前端页面实现;机器可读类型、枚举和约束以 docs/admin-openapi.yaml 为准。
一、先理解五个稳定 ID
| 字段 | 表示什么 | 谁产生 | 前端能否产生 | 主要用途 |
|---|---|---|---|---|
request_id |
一次 HTTP 请求 | 请求携带 X-Request-ID 时沿用;否则 Fiber 中间件生成 UUID |
业务页面不应为了审计查询临时生成;HTTP 客户端可统一传入自己的全局唯一 ID | 把 Access Log、同一次 HTTP 内的 Audit Event、Integration Log 和 Outbox 串起来 |
correlation_id |
一条可跨 HTTP、Outbox、Asynq、Callback 和外部交互的业务链路 | HTTP 起点默认等于 request_id;进入异步或具体业务后可改为订单号、支付号、Integration ID、任务 ID 等稳定链路值 |
不得根据时间、资源或中文描述推断 | 查询完整业务链路;它不表示技术重试 |
parent_event_id |
一个审计事件的直接父事件 | 批量根事件、异步派生或消费者在创建子事件时传播 | 不生成 | 表示直接因果和批量根子关系,不替代 correlation |
integration_id |
一次外部交互尝试的稳定 ID | Integration Log Writer 生成或调用方提供 | 不生成 | 查询单次外部交互详情,也是轮询链路的重要入口 |
trigger_series + attempt |
同一外部操作的显式技术尝试序列和序号 | 可重试的 Integration 调用方 | 不生成 | 判断第几次重试;没有 series 时只展示单次记录,禁止猜测重试 |
request_id 的实际生命周期
- 浏览器、开放接口调用方或外部回调发起 HTTP 请求。调用方如已提供
X-Request-ID,服务端沿用;否则服务端生成 UUID。 - 服务端把同一个值写入响应头
X-Request-ID,浏览器可读取该响应头用于问题反馈。 - Access Log 把它记录为
request_id,同时审计上下文在 HTTP 起点设置request_id,并默认设置correlation_id=request_id。 - 当前请求内发生业务变更时,Audit Writer 将其写入
tb_audit_event.request_id;发生外部交互时可写入tb_integration_log.request_id;创建可靠事件时可写入tb_outbox_event.request_id。 - 前端只有在事件或 Integration 返回了该值,或运维人员从响应头/Access Log 得到该值时,才调用请求时间线。普通资源详情页不需要先取得
request_id。
不是每个 HTTP 请求都会产生 Audit Event。例如普通列表查询只有 Access Log,没有业务审计事件;此时即使响应头有 X-Request-ID,请求时间线也可能没有业务节点。
request_id 在哪里落库
| 事实 | 存储位置 | request_id 字段 |
correlation_id 字段 |
说明 |
|---|---|---|---|---|
| HTTP 调试事实 | Access Log 文件 | JSON 字段 request_id |
当前访问日志不承担业务 correlation 查询 | 用于按请求排查原始 HTTP;审计时间线不会扫描日志文件 |
| Audit Event | tb_audit_event |
request_id,非空列但允许保存空字符串 |
correlation_id,非空列但允许保存空字符串 |
解释谁对什么资源做了什么 |
| Integration Log | tb_integration_log |
request_id,可空 |
correlation_id,可空 |
解释调用了哪个外部系统、结果和尝试序列 |
| Outbox | tb_outbox_event |
request_id,允许空字符串 |
correlation_id,允许空字符串 |
可靠投递事实;投递成功不等于业务成功 |
| Asynq | 任务 payload 或 Audit Event 的任务资源引用 | 按任务类型选择性携带 | 按任务类型选择性携带 | Redis 队列不是审计查询数据源;查询只展示已持久化引用,不扫描历史队列 |
| 手动轮询运行记录 | tb_polling_manual_trigger_log |
没有该字段 | 没有该字段 | 只承担进度、结果、触发人和卡列表;人工触发命令另写 Audit Event |
二、轮询为什么通常没有 request_id
普通自动轮询由 Scheduler/Asynq Worker 触发,不是 HTTP 请求,因此没有 request_id 是正确语义:
- Worker 调用 Gateway 前创建 Integration Log,生成
integration_id。 - 普通轮询的
tb_integration_log.request_id保持空;trigger_series和correlation_id通常使用该integration_id。 - Gateway 返回后,如果观测结果实际改变卡、设备、套餐或网络状态,Worker 才写 Audit Event。
- 该 Audit Event 的
request_id仍为空,correlation_id使用 Integration ID、Asynq Task ID 或稳定任务标识,从而与外部尝试和资源时间线关联。 - 前端看到
request_id为空时隐藏“请求链路”;correlation_id非空时显示“业务链路”;无论两者是否存在,都可以继续使用integration_id或资源引用。
人工轮询需要区分两个事实:
- 管理员点击“手动触发”的 HTTP 命令会产生 Audit Event,因此该“谁发起了轮询”事件有
request_id。 - 随后真正执行轮询的是 Worker。当前手动队列只携带卡 ID,执行阶段没有原 HTTP
request_id;Gateway 尝试和实际观测变化按 Worker 自身的 Integration ID/correlation 串联。 tb_polling_manual_trigger_log继续显示进度和结果;Audit Event 解释谁触发/取消;Integration Log 解释 Gateway 是否被调用以及调用结果。三类事实不能合并成一张记录。
三、前端选择入口的顺序
前端不应把 request_id 当作所有审计入口的必填条件。统一按以下顺序选择:
- 业务页面已有内部 ID:平台直接调用资源时间线。
- 代理或企业页面已有 ICCID、VirtualNo、分配单号、换货单号等业务 identifier:调用主体资源活动接口。
- 订单、退款、充值、钱包或店铺页面:直接以任一稳定业务 ID 调用资金时间线,关联 ID 由服务端补全。
- 审计节点返回
investigation_refs:按引用字段跳转事件、操作者、资源、请求、correlation 或 Integration 视角。 - 只有
resource_key没有内部 ID:先调用资源精确搜索,零命中或多命中时让用户选择,不自动猜测。 - 必需字段不存在:隐藏入口;不得用名称、中文说明、相近时间、编号前缀或第三方流水猜关系。
四、15 条接口总览
| 接口 | 何时调用 | 必填入参 | 主要返回 |
|---|---|---|---|
GET /api/admin/audit/events |
平台审计中心全局列表或其他节点带筛选跳转 | 无 | EventPage |
GET /api/admin/audit/events/{event_id} |
查看一个稳定审计事件 | event_id |
EventDetail |
GET /api/admin/audit/actors/{kind}/{id}/events |
查看某个操作者行为 | kind、id |
EventPage |
GET /api/admin/audit/resources/search |
只有业务 Key、没有内部资源 ID | resource_type、keyword |
ResourceSearchPage |
GET /api/admin/audit/resources/{resource_type}/{resource_id}/timeline |
平台业务页面或资源引用进入审计 | resource_type、resource_id |
EventPage |
GET /api/admin/audit/requests/{request_id}/timeline |
已有真实 request ID 时调查一次 HTTP | request_id |
LinkTimeline |
GET /api/admin/audit/correlations/{correlation_id}/timeline |
调查跨请求、异步和外部业务链路 | correlation_id |
LinkTimeline |
GET /api/admin/audit/finance/timeline |
从订单、退款、充值、钱包、店铺等进入资金调查 | 至少一个稳定资金条件 | FinanceTimelinePage |
GET /api/admin/audit/risks/overview |
平台风险中心总览 | 无;时间不传时使用在线窗口 | RiskOverview |
GET /api/admin/audit/risks/events |
从风险分桶查看明细 | 无;分页和筛选可选 | RiskEventPage |
GET /api/admin/audit/integrations/overview |
平台 Integration 调查总览 | 无;时间不传时使用在线窗口 | IntegrationOverview |
GET /api/admin/audit/integrations |
外部交互列表和组合筛选 | 无 | IntegrationListPage |
GET /api/admin/audit/integrations/{integration_id} |
查看单次外部交互和尝试序列 | integration_id |
IntegrationDetailResponse |
GET /api/admin/agent/resource-activities/{resource_type}/{identifier} |
代理查看授权范围内资源活动 | resource_type、identifier |
SubjectActivityPage |
GET /api/admin/enterprise/resource-activities/{resource_type}/{identifier} |
企业查看当前有效授权卡或设备活动 | resource_type、identifier |
SubjectActivityPage |
平台 /audit/* 接口仅允许超级管理员和平台账号访问;代理、企业必须使用各自的主体活动接口。全部为 GET,不提供修改、删除、导出、恢复、重试、补偿或风险处置。
五、请求参数字典
通用时间与分页
| 字段 | 类型 | 是否必填 | 含义 |
|---|---|---|---|
created_from |
RFC3339 字符串 | 否 | 起始时间,包含该时刻;未传时从在线留存窗口开始 |
created_to |
RFC3339 字符串 | 否 | 结束时间,不包含该时刻;未传时为当前时间 |
page |
int | 否 | 页码,默认 1 |
page_size |
int | 否 | 每页数量,默认 20,最大 100 |
显式时间早于 retention.online_from 或跨越在线边界时返回“数据已归档”稳定错误,不会从对象存储读取部分结果。Integration 和风险查询最长连续 31 天。
全局事件 GET /audit/events
| 字段 | 类型/枚举 | 来源与用途 |
|---|---|---|
action |
string | 稳定动作编码,使用返回的 action_code |
category |
configuration/reliability/asset/security/identity/business |
动作类别 |
actor_kind |
account/personal_customer/openapi/system_task/scheduled_job/external_system |
操作者类型 |
actor_id |
string | 与 actor_kind 共同定位操作者 |
source |
admin_api/personal_api/openapi/worker/scheduler/callback |
操作入口 |
result |
success/failed/denied/partial/unknown |
业务结果 |
risk |
low/normal/high/critical |
风险等级 |
scope_type |
platform/shop/personal_customer |
业务范围类型 |
scope_id |
string | 业务范围稳定 ID |
resource_type |
Registry 类型 | 资源类型 |
resource_id |
string | 资源内部稳定 ID |
resource_key |
string | 资源业务稳定 Key |
request_id |
string | 可选精确筛选;来自真实 HTTP 请求,不是必填入口 |
correlation_id |
string | 可选精确筛选业务链路 |
created_from/to/page/page_size |
通用字段 | 时间和分页 |
事件详情、操作者和资源
| 接口 | 参数 | 说明 |
|---|---|---|
/audit/events/{event_id} |
path event_id |
来自事件列表或 investigation_refs.event_id |
/audit/actors/{kind}/{id}/events |
path kind/id;query action/result/risk/resource_type/resource_id/created_from/created_to/page/page_size |
kind/id 来自 actor_ref;action 使用返回的稳定编码 |
/audit/resources/search |
query resource_type/keyword/page/page_size |
resource_type 仅 iot_card/device/shop/order/refund;keyword 为精确业务标识 |
/audit/resources/{resource_type}/{resource_id}/timeline |
path resource_type/resource_id;query created_from/created_to/action/result/page/page_size |
path 来自业务页面内部 ID、搜索结果或 resource_refs |
资源搜索 keyword 规则:卡支持 ICCID/VirtualNo,设备支持 VirtualNo/IMEI/SN,店铺使用店铺编号,订单使用订单号,退款使用退款单号。
request 与 correlation 时间线
| 接口 | 参数 | 说明 |
|---|---|---|
/audit/requests/{request_id}/timeline |
path request_id |
来自 Event/Integration 返回字段、响应头或 Access Log;普通轮询为空时不调用 |
/audit/correlations/{correlation_id}/timeline |
path correlation_id |
来自 Event、Integration、Outbox/任务或业务详情稳定字段 |
这两个接口不接受分页,返回在线窗口内全部已持久化关联节点。request 查询会同时返回 access_log_lookup_request_id,供运维复制到 Access Log 检索;接口自身不扫描 Access Log。
资金时间线 GET /audit/finance/timeline
| 字段 | 类型 | 前端来源 |
|---|---|---|
shop_id |
uint | 店铺详情或资金概况 |
wallet_id |
uint | 代理主钱包或资产钱包详情 |
order_id/order_no |
uint/string | 订单列表或详情 |
payment_id/payment_no |
uint/string | 支付记录或已明确返回的支付单号 |
refund_id/refund_no |
uint/string | 退款列表或详情 |
recharge_id/recharge_no |
uint/string | 代理充值或个人资产充值 |
approval_instance_id |
uint | 审批实例 |
third_party_trade_no |
string | 已明确返回的第三方交易号 |
actor_kind/actor_id |
enum/string | 调查某操作者涉及的资金事实,必须成对提供 |
correlation_id |
string | 已有稳定业务链路时使用 |
created_from/to/page/page_size |
通用字段 | 时间和分页 |
调用方至少提供一个稳定资金条件;同一业务的其他 ID 由服务端解析,不要求前端补齐。
风险接口
| 接口 | 参数 | 映射 |
|---|---|---|
/audit/risks/overview |
created_from/created_to/risk/result/action/source |
独立风险中心筛选 |
/audit/risks/events |
上述字段 + page/page_size |
risks[].code→risk、results[].code→result、actions[].code→action、sources[].code→source |
Integration overview/list
overview 和 list 共用以下筛选;overview 另有 bucket=hour/day,list 另有 page/page_size。
| 字段 | 类型/枚举 | 来源与用途 |
|---|---|---|
integration_id |
string | 列表、通知 target 或 investigation_refs 返回的稳定 ID |
provider |
ctcc/cmcc/cucc/wechat_pay/alipay/fuiou/wecom/gateway |
外部服务提供方 |
direction |
inbound/outbound |
入站或出站 |
operation |
OpenAPI enum | 外部操作稳定编码,使用列表/详情返回的 operation |
result |
pending/success/failed/unknown/not_found/invalid_payload/conflict/ignored/merged/rate_limited/completed/cancelled |
原始结果 |
result_category |
processing/succeeded/indeterminate/failed/not_sent |
服务端从 result 派生的固定类别 |
external_id |
string | 外部系统业务或请求标识 |
resource_type/resource_id/resource_key |
string | 本地主要资源稳定引用 |
trigger_source/trigger_scene/trigger_series |
string | 触发来源、业务场景和显式尝试序列 |
state_changed |
bool | 是否改变本地业务状态 |
http_status |
100~599 | 外部 HTTP 状态码 |
provider_code |
string | 外部服务稳定结果码 |
request_id/correlation_id |
string | 已有稳定链路字段时筛选;自动轮询 request_id 为空 |
created_from/to |
通用字段 | 时间范围,最长 31 天 |
当前 operation 枚举为:realname_callback、realname_removal_callback、payment_precreate、payment_query、payment_callback、get_access_token、list_visible_members、list_visible_departments、get_template_detail、upload_approval_attachment、submit_approval、approval_callback、get_approval_detail、get_approval_info、query_realname_status、query_flow、query_card_status、query_device_info、set_speed_tier、stop_card、start_card、set_device_wifi、set_device_switch_mode、switch_device_card、reboot_device、reset_device。前端使用 OpenAPI 或接口返回值,不维护另一份中文到编码映射。
代理与企业主体活动
| 接口 | resource_type |
identifier |
其他参数 |
|---|---|---|---|
/agent/resource-activities/{resource_type}/{identifier} |
iot_card/device/asset_allocation_record/exchange_order/shop/enterprise |
依次使用 ICCID、VirtualNo、分配单号、换货单号、店铺编号、企业编号 | created_from/created_to/page/page_size |
/enterprise/resource-activities/{resource_type}/{identifier} |
仅 iot_card/device |
卡用 ICCID,设备用 VirtualNo | created_from/created_to/page/page_size |
代理店铺范围和企业 ID 只来自认证上下文,前端不能传 shop_id/enterprise_id 证明权限。
六、返回参数字典
统一响应与留存信息
| 字段 | 含义 |
|---|---|
code |
统一响应码,成功为 0 |
msg |
中文响应消息 |
data |
本接口业务数据 |
timestamp |
服务端响应时间 |
retention.online_from |
PostgreSQL 当前可在线查询的最早时间 |
retention.archived_before |
早于该时间的数据已归档,不可通过这些接口读取 |
retention.timezone |
留存边界时区,当前为 Asia/Shanghai |
EventPage、EventDetail 与 EventView
EventPage 返回 total/page/page_size/items[]/retention;EventDetail 返回单个 EventView 并附带 retention。
| EventView 字段 | 含义/前端用法 |
|---|---|
event_id |
稳定审计事件 ID,可打开事件详情 |
occurred_at/created_at |
业务事实发生时间/审计记录写入时间 |
category |
动作类别稳定编码 |
action_code/action_name |
稳定动作编码/中文展示名;筛选使用 code |
summary |
中文事件摘要 |
actor_kind/actor_id/actor_name |
操作者类型、稳定 ID、事件发生时名称快照 |
actor_shop_id/name |
操作者所属店铺快照 |
actor_enterprise_id/name |
操作者所属企业快照 |
source |
admin_api、worker、scheduler、callback 等入口来源 |
request_path/request_method/ip_address/user_agent |
HTTP 来源信息;Worker/Scheduler 可为空 |
scope_type/scope_id/scope_name |
业务范围类型、ID 和名称快照 |
result/risk_level |
结果和风险等级稳定编码 |
error_code/error_summary |
失败或拒绝时的稳定错误码和脱敏摘要 |
request_id |
有值才显示“请求链路”;自动轮询通常为空 |
correlation_id |
有值显示“业务链路” |
parent_event_id |
直接父事件 ID |
batch_total/success_count/fail_count |
批量根事件计数;非批量为 0 |
metadata |
已脱敏动作扩展字段,具体含义由 action_code 定义 |
content_hash |
事件不可变内容摘要 |
resources[] |
事件涉及的全部资源及各自快照 |
investigation_refs |
前端跨视角跳转的唯一稳定来源 |
resources[] 字段:resource_type/resource_id/resource_key/display_name 定位资源;relation 为 primary/affected/reference;role 为资源业务角色;identity_snapshot 为事件发生时身份;before_data/after_data 为该资源变更前后数据;subject_visibility/subject_summary/subject_data 为代理或企业安全投影;sort_order/created_at 为展示顺序和资源关联记录写入时间。
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}。任一目标所需字段不完整时隐藏该入口。
ResourceSearchPage
返回 total/page/page_size/items[]/retention。候选项包含 resource_type/resource_id/resource_key/display_name/identity_snapshot/historical;historical=true 表示当前业务表未命中,只从在线历史事件快照解析,不代表资源当前仍存在。
LinkTimeline
| 字段 | 含义 |
|---|---|
request_id/correlation_id |
本次查询使用的链路值,二者只会对应当前查询视角 |
access_log_lookup_request_id |
可复制到 Access Log 的 request ID |
nodes[] |
按发生时间稳定升序的跨事实节点 |
retention |
Audit 与 Integration 的共同在线边界 |
nodes[] 包含:record_source、node_id、occurred_at、code/title、result/result_name、summary、reference_only、request_id/correlation_id/parent_event_id、resources[]、investigation_refs、fidelity。
record_source 可能是 audit_event、integration_log、outbox_event;由事件资源派生的只读引用还可能是 asynq_task 或 domain_ledger_ref。reference_only=true 只表示引用,不代表该节点独立改变了业务状态。fidelity 包含 request_available、correlation_available、parent_event_available、direct_audit_link_available、stable_resource_available;false 时禁止猜测补齐。
FinanceTimelinePage
返回 total/page/page_size/items[]/retention。每个资金节点包含:
record_source/node_id/occurred_at:事实来源、来源内稳定 ID、发生时间。code/title/result/result_name:来源内稳定编码和中文名称。amount/balance_before/balance_after/currency:金额和余额,单位分,人民币为 CNY;为空表示该节点不承载该金额。shop_id/wallet{resource_type,wallet_id}:店铺和钱包引用。amount_authority{authoritative,table,field,conflict_rule}:是否为权威金额及其数据库表字段;冲突时按 conflict_rule 展示。facts:该事实来源的安全结构化业务字段。investigation_refs:继续进入事件、资源、操作者、request、correlation 或 Integration。
RiskOverview 与 RiskEventPage
RiskOverview 返回:total、服务端选择的 bucket=hour/day、signals/risks/results/actions/sources 分布、trend[] 和 retention。所有分布项统一为 {code,name,count},筛选使用 code、展示使用 name。
signals[].code:high_risk/finance/security/failed/denied/partial/unknown。risks[].code:low/normal/high/critical。results[].code:success/failed/denied/partial/unknown。actions[].code:稳定 action_code。sources[].code:admin_api/personal_api/openapi/worker/scheduler/callback。trend[]:bucket_at/total/high_risk/finance/security/failed/denied/partial/unknown。
RiskEventPage 与 EventPage 结构相同,items[] 只包含固定风险集合内的 EventView。
IntegrationOverview、ListPage 和 Detail
IntegrationOverview 返回 total/anomaly_count/unknown_count/stale_pending_count/state_changed_count/average_duration_ms/p95_duration_ms/results/providers/directions/trend/retention。results[] 为 {code,name,category,count},providers/directions 为 {code,name,count},trend[] 为 {bucket_at,total,succeeded,processing,indeterminate,failed,not_sent}。分布 code 可原样回填 list 筛选;name 只用于展示。
Integration ListPage 返回 total/page/page_size/items[]/retention。每项包含:
integration_id:详情入口。provider/provider_name、direction/direction_name、operation/operation_name:稳定编码和中文名。resource{type,id,key}:type/id 均存在时可进入资源时间线。result/result_name/result_category:原始结果、中文名和派生类别。duration_ms/state_changed/created_at:耗时、本地状态是否变化和创建时间。request_id/correlation_id:分别控制请求链路和业务链路入口;自动轮询 request_id 可为空。
Integration Detail 按分组返回:
| 分组 | 字段与用途 |
|---|---|
identity |
integration_id/provider/provider_name/direction/direction_name/operation/operation_name/external_id |
resource |
type/id/key;type/id 齐全时进入资源时间线 |
trigger |
source/scene/series/attempt;series 为空时不拼接其他重试 |
result |
code/name/category/http_status/provider_code/provider_message/duration_ms/state_changed/recovery_strategy;本接口只展示,不执行恢复 |
content |
已脱敏 request_summary/response_summary/metadata/content_hash |
linkage |
request_id/correlation_id/audit_event_id;稳定事件跳转优先使用 investigation_refs 中的 event_id |
timestamps |
scheduled_at/started_at/created_at/updated_at |
attempts[] |
同 series 的 integration_id/attempt/operation/operation_name/sent/result/result_name/result_category/duration_ms/state_changed/created_at |
fidelity |
trigger_series_available/attempt_sequence_reliable/correlation_available/resource_id_available/provider_message_fidelity |
retention |
在线留存边界 |
SubjectActivityPage
代理与企业安全活动返回 resource/total/page/page_size/items[]/retention。
resource与related_resources[]:resource_type/resource_id/resource_key/display_name安全摘要;主体前端不得据此调用平台/audit/*。items[].action_code/action_name:安全动作编码和中文名。items[].subject_summary/subject_data:写入时生成的主体安全摘要和白名单业务字段,不是平台 before/after 删除字段后的结果。items[].result/occurred_at:结果和发生时间。- 响应不包含平台 actor、risk、内部原因、before/after、Audit Event ID、request_id、correlation_id、Integration 内容或 investigation_refs。
七、跨视角只读接口
| 视角 | 接口 | 入参来源 | 响应重点 |
|---|---|---|---|
| 请求链路 | 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/personal_customer/openapi/system_task/scheduled_job/external_system。代理和企业活动响应不得包含 investigation_refs。
八、完整调用链
HTTP 同步业务操作
- 前端调用现有业务写接口;可不传
X-Request-ID,服务端会生成并通过响应头返回。 - HTTP 中间件建立
request_id,审计上下文初始设置correlation_id=request_id。 - 业务变更与 Audit Event 在同一事务提交,事件写入
request_id/correlation_id和资源快照。 - 前端从业务资源页用资源 ID 查看时间线,或从 EventView 的
request_id查看该请求链路。 - 请求时间线只返回已经落入 Audit、Integration、Outbox 的节点;Access Log 需另用
access_log_lookup_request_id检索。
HTTP → Outbox → Asynq/Worker
- HTTP 操作产生
request_id,业务确定或沿用correlation_id。 - 创建 Outbox 时,未显式传入的 request/correlation/parent 从审计上下文继承并写入
tb_outbox_event。 - Relay 将三个字段随 envelope 交给消费者;需要继续入 Asynq 的任务在 payload 中显式携带。
- Worker 恢复系统操作者并写子 Audit Event;有外部调用时另写 Integration Log。
- 前端用 correlation 时间线查看跨进程链路;
record_source区分 Audit、Outbox、Integration 和任务引用,不能把 Outbox delivered 当作业务成功。
外部 Callback
- Callback 同样经过 HTTP RequestID 中间件,因此会有
request_id。 - Integration Log 先记录入站外部交互;correlation 可等于 request ID,也可使用 payment_no、审批 SPNo 等更稳定业务键。
- Callback 实际改变本地业务事实时,以
external_systemactor 写 Audit Event;没有状态变化时只保留 Integration Log。 - 前端从 Integration detail 的 request/correlation/resource 引用继续调查。
自动轮询
- Scheduler/Asynq 选择卡并执行 Worker,没有 HTTP request,因此不生成
request_id。 - Worker 创建 Gateway Integration Log:
integration_id=trigger_series=correlation_id,request_id=null。 - Gateway 结果若改变内部事实,Audit Event 使用同一 correlation,actor 为
system_task,source 为worker。 - 前端从 Integration 调查中心、资源时间线或 correlation 时间线进入;隐藏“请求链路”。
人工即时刷新与手动轮询入队
- “人工即时刷新卡数据”在一个 HTTP 用例内直接执行 Gateway 查询:有 request_id,外部尝试可继承该 request/correlation,能从请求时间线串起。
- “手动触发轮询”先记录 HTTP 触发 Audit Event,因此触发命令有 request_id;但当前 Redis 手动队列只保存 card ID,后续 Worker 没有原 request/correlation,执行阶段按新的 Integration ID 建链。
- 因此当前不能仅凭 request_id 从“手动触发事件”自动跳到后续 Gateway 轮询尝试。前端分别展示手动任务进度、触发审计和资源/Integration 活动,不按时间拼接。若产品要求强关联,需要单独实施稳定 trigger/correlation 传播,不属于本文前端接入范围。
资产详情
- 调用
GET /api/admin/assets/resolve/{identifier}。 - 平台读取
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。 - 代理读取
data.iccid或data.virtual_no,调用对应/agent/resource-activities/...。 - 字段缺失时隐藏入口;企业不调用 resolve,也不回退平台接口。
订单
- 调用
GET /api/admin/orders/{id},读取data.id。 - “审计记录”调用
GET /api/admin/audit/resources/order/{id}/timeline。 - “资金链路”调用
GET /api/admin/audit/finance/timeline?order_id={id}&page=1&page_size=20。 - Payment、Refund、钱包等关联由服务端解析,前端不补猜。
退款
- 调用
GET /api/admin/refunds/{id},读取data.id和可选data.approval_instance_id。 - 审计调用
resources/refund/{id}/timeline,资金调用finance/timeline?refund_id={id}。 - 审批实例 ID 非零时再调用
resources/approval_instance/{approval_instance_id}/timeline。 - 审批字段缺失只隐藏审批入口,不影响退款审计与资金链路。
钱包
- 调用
GET /api/admin/assets/{identifier}/wallet,读取data.wallet_id/resource_type/resource_id。 - “资金链路”调用
finance/timeline?wallet_id={wallet_id}。 - “资产审计”调用
resources/{resource_type}/{resource_id}/timeline。 - 两组稳定字段分别判断,不使用交易备注或 reference 编号前缀推断资源。
通知
- 点击通知后先调用
GET /api/admin/notifications/{id}/target。 - 仅当
data.available=true时展示跳转。 data.target_type=integration_log且data.target_key非空时,将 target key 原样作为integration_id调用GET /api/admin/audit/integrations/{target_key}。- 其他 target type 先进入对应业务详情,再按本文业务页面矩阵进入审计;不可用时只展示通知正文。
风险节点
- 调用
GET /api/admin/audit/risks/overview?created_from={from}&created_to={to}。 - 点击风险、结果、动作或来源分桶时,将相同时间范围和对应稳定编码带入
GET /api/admin/audit/risks/events。 - 从明细
items[].investigation_refs直接进入事件、操作者、资源、request、correlation 或 Integration 视角。 - 缺少的引用入口隐藏;风险中心不提供处置、封禁或恢复按钮。
九、统一降级与事实边界
- 缺少目标接口必需的稳定 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/*。