修正数据
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 7m55s

This commit is contained in:
2026-04-27 18:10:08 +08:00
parent bb33232b1b
commit fe4c545308
57 changed files with 4477 additions and 226 deletions

View File

@@ -0,0 +1,2 @@
schema: spec-driven
created: 2026-04-27

View File

@@ -0,0 +1,160 @@
## Context
当前系统已有 `tb_account_operation_log`,但该模型以账号为中心(如 `target_account_id``target_username`),不适合承载资产域(卡/设备)高频敏感操作。现有资产相关写操作分散在多个模块:
- `iot_card`:分配、回收、系列绑定、轮询开关、实名策略、手动实名、删除
- `device`:删除、分配回收、绑定解绑、系列绑定、设备停复机、网关远程控制
- `asset`:统一入口停复机、停用、轮询状态、实名策略
- `auto-stop-resume`:轮询触发自动停复机
这些链路当前多为业务日志zap缺少可结构化查询的审计落库无法稳定支持安全审计、操作追责与问题复盘。
约束:
- 必须遵循 `Handler -> Service -> Store -> Model`,审计写入在 Service 层触发。
- 审计能力按业务域拆分,本次仅实现资产域,不做全局万能日志表。
- 主流程性能不可明显退化,审计写入采用异步非阻塞。
- 不新增自动化测试文件,采用 PostgreSQL MCP + Postman/curl 手工验证。
## Goals / Non-Goals
**Goals:**
- 新增资产域专用审计日志模型、存储与服务(`tb_asset_operation_log` + `asset_audit`)。
- 覆盖卡与设备敏感写操作,要求成功/失败/拒绝全部记录。
- 统一日志字段:操作人、时间、动作、目标资产、变更前后、请求上下文、结果。
- 在现有模块中实现可复用的审计调用模式,减少重复拼装逻辑。
- 提供可回滚的迁移方案与明确的手工验收清单。
**Non-Goals:**
- 本阶段不实现通用“跨域审计查询平台”。
- 本阶段不改造账号域日志(`tb_account_operation_log`)历史数据。
- 本阶段不新增审计查询 API先完成采集落库查询按 DB 手工验证)。
## Decisions
### 决策1资产域独立日志模型与表
**选择**:新增 `tb_asset_operation_log`,不复用 `tb_account_operation_log`
**理由**
- 资产日志与账号日志目标对象不同,字段语义差异大。
- 独立表可避免“万能表”字段污染,支持未来按域继续拆分(财务/权限等)。
- 资产操作体量高,独立索引策略可控。
**备选方案**:复用 `tb_account_operation_log` 增加 nullable 字段。
**放弃原因**:语义混杂、索引冲突、后续演进成本高。
---
### 决策2统一资产审计服务 + 结构化日志构建器
**选择**:新增 `internal/service/asset_audit`,提供统一 `LogOperation(ctx, entry)`;各业务 Service 在成功/失败/拒绝节点调用。
**理由**
- 降低每个模块重复组装字段成本。
- 便于统一控制日志格式、字段裁剪、异常降级。
- 与现有账号审计模式一致,降低团队理解成本。
**备选方案**:每个业务 Service 直接写 Store。
**放弃原因**:重复代码多,格式易漂移,难做统一治理。
---
### 决策3全结果态记录success/failed/denied
**选择**:结果字段使用 `result_status`(成功/失败/拒绝),并记录 `error_code/error_msg`(失败或拒绝时)。
**理由**
- 仅记录成功不足以支撑安全审计(越权尝试、失败操作同样关键)。
- 便于风控与运维排查(失败高发点、越权热点)。
**备选方案**:只记录成功。
**放弃原因**:审计链不完整。
---
### 决策4前后镜像字段规范化
**选择**`before_data/after_data` 统一为 JSONB
- create/绑定类:`before_data` 可为空,`after_data` 必填关键字段
- update/状态流转类:`before_data``after_data` 同时记录
- delete/解绑类:`before_data` 必填,`after_data` 可为空或最小状态
**理由**
- 满足“从什么变成什么”的核心诉求。
- 便于后续做差异化检索与审计导出。
---
### 决策5依赖注入与接入矩阵
**选择**:在 bootstrap 注入 `assetAuditService` 到以下服务:
- `iot_card.Service`
- `device.Service`
- `iot_card.StopResumeService`
- `asset.LifecycleService`
- `polling.AssetPollingService`(设备轮询开关路径)
- `device_import.Service` / `iot_card_import.Service`(任务创建记录)
**理由**
- 关键写操作分布在多个服务,必须覆盖所有真实入口。
- 避免仅在 Handler 记录导致丢失 Service 内部失败/回滚细节。
---
### 决策6异步写入 + 失败不阻断
**选择**:审计写入使用 Goroutine 异步落库,写入失败仅记录 Error 日志,不影响主业务结果。
**理由**
- 符合当前项目审计日志规范。
- 避免写操作主路径被审计 IO 放大。
**补充约束**
- 单条日志大小限制(对大字段做截断/脱敏),避免超大 JSON 影响 DB。
- 脱敏字段(如 WiFi 密码)仅记录摘要,不明文落库。
---
### 决策7常量与操作类型字典化
**选择**:在 `pkg/constants` 定义资产审计操作类型、结果类型、目标类型常量,禁止硬编码。
**理由**
- 统一语义,避免多模块字符串漂移。
- 便于统计与后续扩展。
## Risks / Trade-offs
- **[风险] 日志量增长导致表膨胀和查询变慢**
**缓解**:增加组合索引(资产、操作人、时间、结果),后续按月归档策略预留。
- **[风险] before/after 组装不一致,影响可读性**
**缓解**:统一字段模板与 helper代码评审按固定清单检查。
- **[风险] 异步写入在进程异常退出时丢少量日志**
**缓解**:接受该权衡;关键安全场景后续可升级为异步队列化写入。
- **[风险] 远程控制接口包含敏感参数(如密码)**
**缓解**:明确脱敏规则,禁止明文入 `after_data`
- **[权衡] 全量记录失败/拒绝会增加写入量**
**接受**:审计完整性优先于少量存储成本。
## Migration Plan
1. 新增模型与迁移:`tb_asset_operation_log`(含必要索引)。
2. 新增 `asset_audit` store/service并在 bootstrap 完成注入。
3. 按操作矩阵分批接入:
- 第一批:停复机、绑定解绑、分配回收、停用、实名策略、轮询开关
- 第二批:远程控制、导入任务创建、删除/批量删除
4. 补充常量与日志构建 helper统一字段格式与脱敏。
5. 使用 PostgreSQL MCP + Postman/curl 执行手工验收输出证据请求、响应、DB 快照)。
**回滚策略:**
- 业务回滚:关闭审计调用开关(或临时空实现),不影响主流程。
- 数据回滚:执行 migration down 删除新表。
## Open Questions
- 是否在本期即提供后台审计查询 API还是维持 DB 手工查询到下一期?
- `after_data` 的最大存储体积阈值定为多少(如 16KB/32KB
- 是否需要为“自动停复机(系统触发)”定义专门 `operator_type`system常量

View File

@@ -0,0 +1,39 @@
## Why
当前系统仅在账号、微信配置、代理充值等少量模块落了审计日志,卡与设备的大量敏感写操作(停复机、绑卡解绑、分配回收、远程控制、实名策略、轮询开关、停用等)缺少统一落库审计,出现问题时难以回答“谁在什么时间做了什么、从什么变成什么、结果如何”。
随着资产规模和运维复杂度增长,该缺口已经影响安全审计、问题追溯和责任界定,需尽快补齐资产域操作日志能力并做全量覆盖。
## What Changes
- `feature-001-asset-audit-domain-model`:新增资产域专用审计日志能力,建设独立日志模型与存储(不复用账号日志表)。
- `feature-002-asset-audit-full-coverage`:覆盖卡与设备相关全部敏感写操作,包含成功、失败、拒绝三类结果。
- `feature-003-asset-audit-context-complete`:每条日志必须记录操作人、操作时间、操作内容、变更前后数据、请求上下文与结果。
- `feature-004-asset-audit-service-integration`:在 `Handler -> Service -> Store -> Model` 分层内完成审计服务注入与调用,主流程非阻塞。
- `feature-005-asset-audit-observability`:补充文档与手工验收方案,保证审计数据可查询、可追溯、可核对。
## Capabilities
### New Capabilities
- `asset-operation-audit`:资产域操作审计能力,定义资产日志数据模型、记录规范、覆盖范围与落库语义(含成功/失败/拒绝)。
### Modified Capabilities
- `iot-device`:设备分配、远程控制、导入等场景从“原则要求记录日志”升级为“必须按统一资产审计字段规范落库”。
- `auto-stop-resume`:停复机相关流程明确使用资产域审计日志模型并记录操作结果、前后状态。
## Impact
- 影响模块:
- `internal/model`:新增资产操作日志模型(独立于账号日志模型)。
- `internal/store/postgres`:新增资产日志存储与查询基础能力。
- `internal/service`:卡、设备、资产、停复机、轮询管控等写操作接入审计日志。
- `internal/bootstrap`:注入资产审计服务依赖。
- `pkg/constants`:新增资产审计操作类型与结果常量。
- 影响 API
- 对现有接口契约原则上无破坏性变更;行为变化为“写操作新增审计落库”。
- 影响数据:
- 新增资产审计日志表及索引,用于按资产、操作人、时间、操作类型追溯。
- 影响性能:
- 审计写入采用异步非阻塞;控制单次日志体大小,避免对主链路造成显著延迟。
- 验证计划:
- 按项目约束使用 PostgreSQL MCP + Postman/curl 手工验证,不新增自动化测试文件。

View File

@@ -0,0 +1,64 @@
## ADDED Requirements
### Requirement: 资产域操作日志使用独立数据模型
系统 SHALL 为资产域操作日志使用独立数据模型与数据表,不得复用账号域日志表;资产日志模型 MUST 支持记录资产类型、资产ID、资产标识符、操作动作、操作结果、前后镜像和请求上下文。
#### Scenario: 新增资产日志表并独立于账号日志
- **WHEN** 系统初始化资产域审计能力
- **THEN** 系统使用独立的 `tb_asset_operation_log` 存储资产日志,且不写入 `tb_account_operation_log`
#### Scenario: 资产日志表不使用外键约束
- **WHEN** 创建资产日志表结构
- **THEN** 表间关联通过 ID 字段维护,不创建数据库外键和 GORM 关联标签
### Requirement: 资产敏感写操作必须全量记录
系统 SHALL 对卡和设备相关敏感写操作进行全量审计记录,结果态 MUST 覆盖 `success``failed``denied`
#### Scenario: 成功操作写入 success 日志
- **WHEN** 设备分配、卡绑定、手动实名、停用等写操作执行成功
- **THEN** 系统写入 `result_status=success` 的资产操作日志
#### Scenario: 业务失败写入 failed 日志
- **WHEN** 写操作执行过程中发生网关失败或数据库失败
- **THEN** 系统写入 `result_status=failed` 的资产操作日志,并记录错误码与错误摘要
#### Scenario: 权限或规则拒绝写入 denied 日志
- **WHEN** 操作被权限规则、保护期规则或业务前置条件拒绝
- **THEN** 系统写入 `result_status=denied` 的资产操作日志,并记录拒绝原因
### Requirement: 审计日志必须包含完整上下文
系统 SHALL 在资产日志中记录“谁、何时、做了什么、从什么变成什么”,并包含请求链路上下文。
#### Scenario: 记录操作人和时间
- **WHEN** 生成任一资产操作日志
- **THEN** 日志包含 `operator_id``operator_type``operator_name``created_at`
#### Scenario: 记录前后镜像
- **WHEN** 记录状态流转或配置修改类操作
- **THEN** 日志同时包含 `before_data``after_data`,可直接体现变更差异
#### Scenario: 记录请求上下文
- **WHEN** 记录资产操作日志
- **THEN** 日志包含 `request_id``ip_address``user_agent``request_path``request_method`
### Requirement: 审计写入异步且不阻塞主流程
系统 SHALL 采用异步方式写入资产审计日志,日志写入失败 MUST 不影响业务主流程结果。
#### Scenario: 异步写入
- **WHEN** 业务操作完成并触发审计记录
- **THEN** 主流程先返回业务结果,日志由异步流程落库
#### Scenario: 日志写入失败降级
- **WHEN** 资产日志落库失败
- **THEN** 系统仅记录 Error 级别应用日志,不回滚已成功的主业务操作
### Requirement: 敏感字段脱敏与日志体积控制
系统 SHALL 对敏感字段执行脱敏处理,并对日志体积设置上限,避免泄露与性能风险。
#### Scenario: 远程配置敏感字段脱敏
- **WHEN** 记录设备 WiFi/密码等敏感配置变更日志
- **THEN** `before_data`/`after_data` 中不得出现明文密码,仅保留掩码或摘要
#### Scenario: 超长数据裁剪
- **WHEN** 业务上下文数据超过日志体积阈值
- **THEN** 系统对超长字段进行裁剪并保留裁剪标记,保证日志写入稳定

View File

@@ -0,0 +1,35 @@
## ADDED Requirements
### Requirement: 自动停复机流程必须写入资产审计日志
系统 SHALL 在自动停机与自动复机流程中写入资产审计日志,且日志结果态 MUST 覆盖成功与失败。
#### Scenario: 自动停机成功写入日志
- **WHEN** 轮询判定流量耗尽并成功停机
- **THEN** 系统写入资产审计日志,记录操作类型、停机原因、变更前后网络状态与 `result_status=success`
#### Scenario: 自动停机失败写入日志
- **WHEN** 自动停机在重试后仍失败
- **THEN** 系统写入资产审计日志,记录 `result_status=failed`、错误摘要与重试信息摘要
#### Scenario: 自动复机成功写入日志
- **WHEN** 满足复机条件且自动复机成功
- **THEN** 系统写入资产审计日志,记录复机前后状态、触发来源与 `result_status=success`
#### Scenario: 自动复机失败写入日志
- **WHEN** 自动复机执行失败
- **THEN** 系统写入资产审计日志,记录 `result_status=failed` 与失败原因
### Requirement: 手动停复机必须与自动流程使用同一审计标准
系统 SHALL 对手动停机/复机使用与自动流程一致的资产审计字段规范,并在拒绝场景记录 denied 日志。
#### Scenario: 手动停机被拒绝时记录 denied 日志
- **WHEN** 用户手动停机因未实名或保护期规则被拒绝
- **THEN** 系统写入 `result_status=denied` 的资产审计日志,并记录拒绝原因
#### Scenario: 手动复机被拒绝时记录 denied 日志
- **WHEN** 用户手动复机因保护期规则被拒绝
- **THEN** 系统写入 `result_status=denied` 的资产审计日志,并记录拒绝原因
#### Scenario: 手动停复机成功时记录变更镜像
- **WHEN** 用户手动停机或复机成功
- **THEN** 系统在日志中记录 `before_data``after_data`,体现网络状态和停机原因的变化

View File

@@ -0,0 +1,31 @@
## ADDED Requirements
### Requirement: 设备敏感写操作必须写入资产审计日志
系统 SHALL 对设备能力中的敏感写操作写入资产域审计日志,包括但不限于:删除设备、绑定/解绑卡、批量分配/回收、设备停机/复机、远程控制(限速/WiFi/切卡/切卡模式/重启/恢复出厂)、批量导入任务创建。
#### Scenario: 设备分配与回收记录审计日志
- **WHEN** 运营人员执行设备批量分配或回收
- **THEN** 系统记录资产审计日志,包含目标设备列表、操作前后归属信息、操作结果
#### Scenario: 绑定与解绑记录审计日志
- **WHEN** 平台用户执行设备绑卡或解绑
- **THEN** 系统记录资产审计日志包含设备ID、卡ID、插槽信息和前后绑定状态
#### Scenario: 设备停复机记录审计日志
- **WHEN** 用户对设备执行停机或复机
- **THEN** 系统记录资产审计日志,包含处理卡数量、成功数、失败数、失败原因摘要
#### Scenario: 远程控制记录审计日志
- **WHEN** 用户执行限速、WiFi设置、切卡、切卡模式、重启、恢复出厂
- **THEN** 系统记录资产审计日志,包含操作类型、关键参数摘要、执行结果和错误信息(如失败)
### Requirement: 设备操作拒绝和失败场景也必须审计
系统 SHALL 在设备操作被拒绝或执行失败时同样写入审计日志,不得仅记录成功操作。
#### Scenario: 规则拒绝写入 denied 日志
- **WHEN** 设备操作因保护期或权限限制被拒绝
- **THEN** 系统写入 `result_status=denied` 的资产审计日志,并记录拒绝原因
#### Scenario: 网关或数据库失败写入 failed 日志
- **WHEN** 设备操作执行过程中出现网关调用失败或数据库更新失败
- **THEN** 系统写入 `result_status=failed` 的资产审计日志,并记录错误码与错误摘要

View File

@@ -0,0 +1,60 @@
## 0. 验证准备与覆盖矩阵确认
- [x] 0.1 梳理资产敏感写操作覆盖矩阵(卡/设备/统一资产入口/自动停复机/导入任务创建),明确每个操作对应 `operation_type`
- [x] 0.2 定义日志字段验收清单:`operator_*``asset_*``operation_*``before_data``after_data``request_*``result_*`
- [x] 0.3 准备手工验收数据与脚本Postman/curl + PostgreSQL MCP 查询语句),覆盖 success/failed/denied 三类结果
## 1. 资产域日志模型与迁移
- [x] 1.1 新增资产操作日志 Model`tb_asset_operation_log`)与 JSONB 字段结构,确保无外键/无 GORM 关联标签
- [x] 1.2 新增迁移文件up/down创建资产日志表和索引按资产、操作人、时间、结果等维度
- [x] 1.3 新增 Store 能力Create + 常用查询基础方法),满足异步写入与后续审计检索
- [x] 1.4 使用 PostgreSQL MCP 验证表结构、索引、字段类型与约束符合设计
## 2. 审计基础设施与常量
- [x] 2.1 在 `pkg/constants` 新增资产审计常量:操作类型、结果类型、资产类型、系统操作者类型等
- [x] 2.2 新增 `asset_audit` 服务与统一写入接口(异步落库、失败不阻断主流程)
- [x] 2.3 新增日志构建 helper统一 before/after、请求上下文、错误信息组装
- [x] 2.4 在 bootstrap 完成依赖注入(`iot_card``device``stop_resume``asset lifecycle``asset polling`、导入服务)
- [x] 2.5 编译校验与静态检查(`gofmt``go build`)确保注入链路无回归
## 3. IoT 卡相关操作接入审计
- [x] 3.1 接入单卡分配/回收审计日志(包含前后归属、结果态)
- [x] 3.2 接入卡系列绑定、轮询开关、实名策略更新审计日志
- [x] 3.3 接入手动实名状态更新审计日志(必须记录 before/after
- [x] 3.4 接入卡删除/批量删除审计日志
- [x] 3.5 对卡相关拒绝与失败路径补充 denied/failed 审计日志
- [ ] 3.6 手工验证卡操作日志完整性success/failed/denied + before/after
## 4. 设备相关操作接入审计
- [x] 4.1 接入设备删除、分配、回收、系列绑定审计日志
- [x] 4.2 接入设备绑卡/解绑审计日志(记录设备、卡、插槽与状态变化)
- [x] 4.3 接入设备停机/复机审计日志(记录成功数、失败数、失败摘要)
- [x] 4.4 接入设备远程控制审计日志(限速/WiFi/切卡/切卡模式/重启/恢复出厂)
- [x] 4.5 落实敏感字段脱敏WiFi 密码等不得明文写入日志)
- [ ] 4.6 手工验证设备操作日志(含敏感字段脱敏校验)
## 5. 统一资产入口与停复机链路接入
- [x] 5.1 在统一资产入口相关写操作中补齐审计日志(停复机、停用、轮询状态、实名策略)
- [x] 5.2 在自动停复机链路补齐审计日志(自动停机/自动复机成功与失败)
- [x] 5.3 在手动停复机拒绝场景补齐 denied 审计日志(未实名、保护期等)
- [x] 5.4 校验系统触发操作的操作者语义(`operator_type=system` 等)
- [ ] 5.5 手工验证统一入口与停复机链路审计闭环
## 6. 导入任务创建与批量链路补齐
- [x] 6.1 接入设备导入任务创建审计日志(记录任务参数摘要与创建结果)
- [x] 6.2 接入卡导入任务创建审计日志(记录任务参数摘要与创建结果)
- [ ] 6.3 校验批量操作日志的聚合字段(`batch_total/success_count/fail_count`
- [ ] 6.4 手工验证导入与批量链路审计数据可追溯
## 7. 文档与最终验收
- [x] 7.1 编写功能总结文档(`docs/{feature-id}/`),说明字段规范、覆盖范围、脱敏规则、查询示例
- [x] 7.2 更新 README 相关章节(资产审计日志能力与排障入口)
- [ ] 7.3 完成全链路手工验收:卡与设备典型操作各覆盖 success/failed/denied 至少一例
- [ ] 7.4 输出验收证据:接口请求响应、日志样例、数据库快照与关键 SQL 查询结果

View File

@@ -0,0 +1,58 @@
# 资产审计日志验收准备
## 0.1 资产敏感写操作覆盖矩阵
| 业务域 | 场景 | `operation_type` | 主要入口 |
|---|---|---|---|
| IoT 卡 | 分配 | `card_allocate` | `iot_card.Service.AllocateCards` |
| IoT 卡 | 回收 | `card_recall` | `iot_card.Service.RecallCards` |
| IoT 卡 | 系列绑定 | `card_series_binding` | `iot_card.Service.BatchSetSeriesBinding` |
| IoT 卡 | 轮询开关 | `card_polling_status` | `iot_card.Service.UpdatePollingStatus/BatchUpdatePollingStatus` |
| IoT 卡 | 实名策略 | `card_realname_policy` | `iot_card.Service.UpdateRealnamePolicy` |
| IoT 卡 | 手动实名状态 | `card_realname_status` | `iot_card.Service.ManualUpdateRealnameStatus` |
| IoT 卡 | 删除/批量删除 | `card_delete` / `card_batch_delete` | `iot_card.Service.DeleteCard/BatchDeleteCards` |
| IoT 卡停复机 | 自动停机/复机 | `card_auto_stop` / `card_auto_start` | `iot_card.StopResumeService.stopCardWithRetry/resumeSingleCard` |
| IoT 卡停复机 | 手动停机/复机 | `card_manual_stop` / `card_manual_start` | `iot_card.StopResumeService.ManualStopCard/ManualStartCard` |
| 设备 | 删除 | `device_delete` | `device.Service.Delete` |
| 设备 | 分配/回收 | `device_allocate` / `device_recall` | `device.Service.AllocateDevices/RecallDevices` |
| 设备 | 系列绑定 | `device_series_binding` | `device.Service.BatchSetSeriesBinding` |
| 设备 | 绑卡/解绑 | `device_bind_card` / `device_unbind_card` | `device.Service.BindCard/UnbindCard` |
| 设备 | 停机/复机 | `device_stop` / `device_start` | `device.Service.StopDevice/StartDevice` |
| 设备远程控制 | 限速 | `device_speed_limit` | `device.Service.GatewaySetSpeedLimit` |
| 设备远程控制 | WiFi 设置 | `device_set_wifi` | `device.Service.GatewaySetWiFi` |
| 设备远程控制 | 切卡 | `device_switch_card` | `device.Service.GatewaySwitchCard` |
| 设备远程控制 | 切卡模式 | `device_switch_mode` | `device.Service.GatewaySwitchMode` |
| 设备远程控制 | 重启/恢复出厂 | `device_reboot` / `device_reset` | `device.Service.GatewayRebootDevice/ResetDevice` |
| 统一资产入口 | 停用 | `asset_deactivate` | `asset.LifecycleService.DeactivateIotCard/DeactivateDevice` |
| 统一资产入口 | 轮询开关 | `asset_polling_status` | `polling.AssetPollingService.UpdatePollingStatus` |
| 统一资产入口 | 实名策略 | `asset_realname_policy` | `device.Service.UpdateRealnamePolicy`(设备路径) |
| 导入任务 | 设备导入任务创建 | `device_import_task_create` | `device_import.Service.CreateImportTask` |
| 导入任务 | 卡导入任务创建 | `iot_card_import_task_create` | `iot_card_import.Service.CreateImportTask` |
## 0.2 审计字段验收清单
| 字段组 | 核对项 | 说明 |
|---|---|---|
| `operator_*` | `operator_id/operator_type/operator_name` | 系统触发场景 `operator_type=system``operator_id` 可为空 |
| `asset_*` | `asset_type/asset_id/asset_identifier` | 设备使用虚拟号,卡使用 ICCID批量/导入场景允许按任务摘要记录 |
| `operation_*` | `operation_type/operation_desc` | `operation_type` 必须来自 `pkg/constants/asset_audit.go` |
| `before_data/after_data` | 变更镜像 | 状态/配置修改类要求体现前后差异 |
| `request_*` | `request_id/ip_address/user_agent/request_path/request_method` | 由日志中间件注入到 `context`,审计统一读取 |
| `result_*` | `result_status/error_code/error_msg` | 覆盖 `success/failed/denied`;失败/拒绝需记录错误摘要 |
| 批量聚合 | `batch_total/success_count/fail_count` | 批量与设备停复机场景需写入聚合统计 |
## 0.3 手工验收数据与脚本
### 接口回放建议Postman/curl
1. 成功样例:设备分配、卡分配、设备远程控制(限速)
2. 失败样例:远程控制网关失败、非法设备 ID、事务失败
3. 拒绝样例:停复机保护期、越权分配、无效实名策略
### SQL 脚本
- 统一查询脚本:`docs/add-asset-operation-audit-log/手工验收脚本.sql`
- 重点核对:
- 同一操作存在 `success/failed/denied` 三类结果
- `before_data/after_data` 存在且字段合理
- WiFi 密码字段已脱敏(不出现明文)