This commit is contained in:
@@ -1,8 +1,326 @@
|
||||
# 跨视角调查与前端导航契约
|
||||
# 审计链路与前端接入指南
|
||||
|
||||
本文对应 `build-multi-view-audit-center` 任务 9.5,冻结 request、correlation、资金和风险调查接口,以及现有业务页面进入审计中心的第一跳。所有字段路径均位于统一响应的 `response.data` 下;列表字段位于 `items[]`。本文只定义前端调用契约,不包含前端页面实现。
|
||||
本文对应 `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` 的实际生命周期
|
||||
|
||||
1. 浏览器、开放接口调用方或外部回调发起 HTTP 请求。调用方如已提供 `X-Request-ID`,服务端沿用;否则服务端生成 UUID。
|
||||
2. 服务端把同一个值写入响应头 `X-Request-ID`,浏览器可读取该响应头用于问题反馈。
|
||||
3. Access Log 把它记录为 `request_id`,同时审计上下文在 HTTP 起点设置 `request_id`,并默认设置 `correlation_id=request_id`。
|
||||
4. 当前请求内发生业务变更时,Audit Writer 将其写入 `tb_audit_event.request_id`;发生外部交互时可写入 `tb_integration_log.request_id`;创建可靠事件时可写入 `tb_outbox_event.request_id`。
|
||||
5. 前端只有在事件或 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` 是正确语义:
|
||||
|
||||
1. Worker 调用 Gateway 前创建 Integration Log,生成 `integration_id`。
|
||||
2. 普通轮询的 `tb_integration_log.request_id` 保持空;`trigger_series` 和 `correlation_id` 通常使用该 `integration_id`。
|
||||
3. Gateway 返回后,如果观测结果实际改变卡、设备、套餐或网络状态,Worker 才写 Audit Event。
|
||||
4. 该 Audit Event 的 `request_id` 仍为空,`correlation_id` 使用 Integration ID、Asynq Task ID 或稳定任务标识,从而与外部尝试和资源时间线关联。
|
||||
5. 前端看到 `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` 当作所有审计入口的必填条件。统一按以下顺序选择:
|
||||
|
||||
1. 业务页面已有内部 ID:平台直接调用资源时间线。
|
||||
2. 代理或企业页面已有 ICCID、VirtualNo、分配单号、换货单号等业务 identifier:调用主体资源活动接口。
|
||||
3. 订单、退款、充值、钱包或店铺页面:直接以任一稳定业务 ID 调用资金时间线,关联 ID 由服务端补全。
|
||||
4. 审计节点返回 `investigation_refs`:按引用字段跳转事件、操作者、资源、请求、correlation 或 Integration 视角。
|
||||
5. 只有 `resource_key` 没有内部 ID:先调用资源精确搜索,零命中或多命中时让用户选择,不自动猜测。
|
||||
6. 必需字段不存在:隐藏入口;不得用名称、中文说明、相近时间、编号前缀或第三方流水猜关系。
|
||||
|
||||
## 四、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。
|
||||
|
||||
## 七、跨视角只读接口
|
||||
|
||||
| 视角 | 接口 | 入参来源 | 响应重点 |
|
||||
|---|---|---|---|
|
||||
@@ -14,7 +332,7 @@
|
||||
|
||||
以上接口仅允许超级管理员和平台账号访问,全部为 GET。认证身份只来自认证上下文;不提供导出、修改、删除、风险处置、自动封禁、重试、补偿或恢复能力。
|
||||
|
||||
## 资产和组织页面逐行导航
|
||||
### 资产和组织页面逐行导航
|
||||
|
||||
| 源页面 | 前置接口 | `response.data` 稳定字段 | 入口名称与可见条件 | 目标接口与参数映射 | 降级行为 |
|
||||
|---|---|---|---|---|---|
|
||||
@@ -29,7 +347,7 @@
|
||||
| 企业卡列表 | `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` 稳定字段 | 入口名称与可见条件 | 目标接口与参数映射 | 降级行为 |
|
||||
|---|---|---|---|---|---|
|
||||
@@ -45,7 +363,7 @@
|
||||
| 店铺主钱包流水 | `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` 字段 | 入口名称 | 可见条件 | 目标接口与参数 | 降级行为 |
|
||||
|---|---|---|---|---|
|
||||
@@ -56,9 +374,45 @@
|
||||
| `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`。
|
||||
`actor_ref.kind` 使用 `account/personal_customer/openapi/system_task/scheduled_job/external_system`。代理和企业活动响应不得包含 `investigation_refs`。
|
||||
|
||||
## 六条完整调用链
|
||||
## 八、完整调用链
|
||||
|
||||
### HTTP 同步业务操作
|
||||
|
||||
1. 前端调用现有业务写接口;可不传 `X-Request-ID`,服务端会生成并通过响应头返回。
|
||||
2. HTTP 中间件建立 `request_id`,审计上下文初始设置 `correlation_id=request_id`。
|
||||
3. 业务变更与 Audit Event 在同一事务提交,事件写入 `request_id/correlation_id` 和资源快照。
|
||||
4. 前端从业务资源页用资源 ID 查看时间线,或从 EventView 的 `request_id` 查看该请求链路。
|
||||
5. 请求时间线只返回已经落入 Audit、Integration、Outbox 的节点;Access Log 需另用 `access_log_lookup_request_id` 检索。
|
||||
|
||||
### HTTP → Outbox → Asynq/Worker
|
||||
|
||||
1. HTTP 操作产生 `request_id`,业务确定或沿用 `correlation_id`。
|
||||
2. 创建 Outbox 时,未显式传入的 request/correlation/parent 从审计上下文继承并写入 `tb_outbox_event`。
|
||||
3. Relay 将三个字段随 envelope 交给消费者;需要继续入 Asynq 的任务在 payload 中显式携带。
|
||||
4. Worker 恢复系统操作者并写子 Audit Event;有外部调用时另写 Integration Log。
|
||||
5. 前端用 correlation 时间线查看跨进程链路;`record_source` 区分 Audit、Outbox、Integration 和任务引用,不能把 Outbox delivered 当作业务成功。
|
||||
|
||||
### 外部 Callback
|
||||
|
||||
1. Callback 同样经过 HTTP RequestID 中间件,因此会有 `request_id`。
|
||||
2. Integration Log 先记录入站外部交互;correlation 可等于 request ID,也可使用 payment_no、审批 SPNo 等更稳定业务键。
|
||||
3. Callback 实际改变本地业务事实时,以 `external_system` actor 写 Audit Event;没有状态变化时只保留 Integration Log。
|
||||
4. 前端从 Integration detail 的 request/correlation/resource 引用继续调查。
|
||||
|
||||
### 自动轮询
|
||||
|
||||
1. Scheduler/Asynq 选择卡并执行 Worker,没有 HTTP request,因此不生成 `request_id`。
|
||||
2. Worker 创建 Gateway Integration Log:`integration_id=trigger_series=correlation_id`,`request_id=null`。
|
||||
3. Gateway 结果若改变内部事实,Audit Event 使用同一 correlation,actor 为 `system_task`,source 为 `worker`。
|
||||
4. 前端从 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 传播,不属于本文前端接入范围。
|
||||
|
||||
### 资产详情
|
||||
|
||||
@@ -102,7 +456,7 @@
|
||||
3. 从明细 `items[].investigation_refs` 直接进入事件、操作者、资源、request、correlation 或 Integration 视角。
|
||||
4. 缺少的引用入口隐藏;风险中心不提供处置、封禁或恢复按钮。
|
||||
|
||||
## 统一降级与事实边界
|
||||
## 九、统一降级与事实边界
|
||||
|
||||
- 缺少目标接口必需的稳定 ID 或 identifier 时隐藏入口,不按名称、中文描述、时间或编号前缀猜测。
|
||||
- 平台只有 Registry Key 时先调用精确资源搜索;零命中或多命中停留在搜索结果。
|
||||
|
||||
Reference in New Issue
Block a user