- 新增 tb_refund_post_process_attempt,每次尝试一条(步骤、触发方式、结果、错误码与信息、耗时) - 退款单增加 asset_post_status/attempts/last_error/next_at;失败按 2^(n-1) 分钟退避(最长 1 小时),10 次后转人工 - 中间失败只写应用日志,成功或转人工写一条结论审计(带总尝试次数、首次失败时间、最后错误码) - 补偿扫描跳过需人工处理与未到重试时间的退款单,Outbox 不再无限重投 - 新增 POST /refunds/:id/asset-post-processing/retry 人工重试 - 停复机指令执行前结束(已是目标状态、条件不再满足、需相反动作)写 skipped 停复机记录 - 迁移 000271 需维护者在测试库执行后再部署 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
72 lines
7.7 KiB
Markdown
72 lines
7.7 KiB
Markdown
## 1. 审计落库策略(第 1 次提交)
|
||
|
||
- [x] 1.1 `internal/infrastructure/audit/registry.go`:`ActionDefinition` 新增 `Persist`,取值为 `always`、`on_success`、`outcome`、`log_only`、`none`;按技术方案 4.1、4.2 为全部可由系统任务或定时任务发起的动作声明策略,`integration.attempt_started` 设为 `none`。
|
||
- [x] 1.2 `writer.go`:
|
||
- 新增 `persistDecision`:人工操作者一律写表;系统任务和定时任务按 `Persist` 处理,未声明时按 `log_only`。
|
||
- `AppendInput` 增加 `Final`;`outcome` 策略在 `Final=false` 时只写日志,`Final=true` 时按业务键 `EventID` 写表。
|
||
- [x] 1.3 `log_only` 和 `on_success` 的失败结果写 `logger.GetAppLogger().Named("audit")`,`msg=audit_event`。字段按 spec 写入,不含快照;成功记 Info,失败记 Warn。
|
||
- [x] 1.4 逐一检查 `AppendAndGet` 的 11 处调用,确保返回 nil 事件时不会出错。
|
||
- [x] 1.5 `pkg/config` 新增 `audit.persist_overrides`(动作编码 → 策略),运行时生效,只作用于系统任务和定时任务操作者。
|
||
- [x] 1.6 `internal/infrastructure/integrationlog/repository.go`:删除 `Start` 中补写 `integration.attempt_started` 的分支;确认 `auditEventIDForSeries` 的查询走索引。
|
||
- [x] 1.7 `internal/governance/auditcoverage`:可由系统任务发起但未声明 `Persist` 的动作,扫描判为失败;更新已移出审计入口的 `AuditEvent` / `DomainLedger` 分类。
|
||
- [x] 1.8 `gofmt`、`go build ./cmd/api ./cmd/worker`、`openspec validate refactor-audit-log-persistence`;提交并推送 8-11。
|
||
|
||
## 2. 退款后处理与停复机跳过记录(第 2 次提交)
|
||
|
||
- [x] 2.1 迁移:
|
||
- 新建 `tb_refund_post_process_attempt`,按月分区,并建立索引;
|
||
- 退款单新增 `asset_post_status`、`asset_post_attempts`、`asset_post_last_error`、`asset_post_next_at`;
|
||
- 补齐 down 脚本。
|
||
- [x] 2.2 `internal/service/refund`:
|
||
- `processRefundAsset` 每次执行都写尝试记录(步骤、触发方式、结果、错误码与错误信息、耗时、关联停复机记录);
|
||
- 失败时按指数退避(最长 1 小时)更新退款单;
|
||
- 达到 10 次后置为需人工处理,并写一条 `outcome` 失败结论审计;
|
||
- 成功时写 `outcome` 成功结论审计,`asset_reset` 同步置为完成。
|
||
- [x] 2.3 Outbox 处理器与 `RecoverRefundPostProcessing` 在执行前检查状态和 `next_at`:未到期、已完成、需人工处理的都跳过;补偿扫描负责拉起已到期的待重试单。
|
||
- [x] 2.4 新增 `POST /refunds/:id/asset-post-processing/retry` 人工重试接口,只允许在需人工处理状态下调用,记为人工重试;在路由 `RouteSpec` 中登记,并生成接口文档。
|
||
- [x] 2.5 停复机指令执行前的重新判断处,按三种结束原因写 `skipped` 停复机记录(已是目标状态、条件不再满足、不允许停复机);限流推迟不写。
|
||
- [x] 2.6 构建、校验、提交并推送 8-11。
|
||
|
||
## 3. 流量采集分表与原始数据(第 3 次提交)
|
||
|
||
- [ ] 3.1 `internal/gateway/client.go`:新增 `WithRawCapture`,`executeWithRetry` 按尝试写入最后一次的明文请求、HTTP 状态、响应体、`code`、`msg`、`trace_id` 和尝试次数;不记录加密报文、签名、`app_id`、密钥和请求头。
|
||
- [ ] 3.2 迁移:
|
||
- 新建 `tb_card_traffic_collection_failure`,按月分区,并建立索引;
|
||
- 采集成功表增加 `carrier_id` 和原始数据列(`raw_request`、`http_status`、`gateway_code`、`gateway_msg`、`gateway_trace_id`、`raw_response`、`raw_response_text`、`raw_truncated`、`gateway_attempts`),新增 D9 中列出的索引。
|
||
- [ ] 3.3 `polling_carddata_handler`:
|
||
- 调用 `QueryFlow` 前挂上收集器;
|
||
- 网关失败时填入错误类别、上游码与信息、耗时;
|
||
- 成功和失败都把原始数据带进 `TrafficObservation`。
|
||
- [ ] 3.4 `internal/application/cardobservation`:`writeCollectionRecord` 按结果分流。成功写成功表(保持"有套餐才写"),失败直接写失败表(不查套餐);原始响应超过 4 KB 时截断并标记。
|
||
- [ ] 3.5 `MaintainPartitions` 改为成功表、失败表共用的四步归档(摘出、导出 `csv.gz.tmp`、校验并写 manifest 后改名、删除),并处理上一轮遗留的已摘出表、清理本地压缩包(默认保留 3 个月);常量改为 `TrafficCollectionRetentionMonths=2`。
|
||
|
||
## 4. 记录查询接口(第 3 次提交)
|
||
|
||
- [ ] 4.1 在 `internal/store/postgres` 中为各记录表实现统一的 `List(ctx, Filter)`;资产标识复用现有资产解析,解析不到时返回空页。
|
||
- [ ] 4.2 采集成功列表 `GET /traffic-collections`、采集失败列表 `GET /traffic-collection-failures`;单卡采集接口增加筛选条件和"包含失败"参数,成功表查询按 `result='ok'` 过滤。
|
||
- [ ] 4.3 停复机记录列表:`iccid` 扩展为资产标识,增加场景、原因、指令号筛选;单卡历史增加动作、结果、来源筛选;新建或重建 D9 中列出的索引。
|
||
- [ ] 4.4 新增卡日流量列表;新增套餐日流量详单列表,原单套餐接口改为分页;新增冲正流水列表,原单套餐接口增加时间范围筛选。
|
||
- [ ] 4.5 新增退款后处理尝试列表;退款列表增加 `asset_post_status` 筛选,列表和详情返回后处理次数、最后错误、下次重试时间。
|
||
- [ ] 4.6 统一校验规则:时间范围必填、跨度不超过 31 天、分页上限;所有接口在 `RouteSpec` 中登记输入输出 DTO,并生成接口文档。
|
||
|
||
## 5. 时间线与测试环境部署配置(第 3 次提交)
|
||
|
||
- [ ] 5.1 先与前端或运营确认是否有页面依赖机器动作的审计,再在 `internal/query/audit` 中让卡和设备时间线合并停复机记录。
|
||
- [ ] 5.2 `docker-compose.prod.yml`:api 挂载 `./api/logs`,worker 挂载 `./worker/logs` 和 `./worker/archive`;两者增加 `MAX_BACKUPS=40`、`MAX_AGE=14`。`.gitea/workflows/deploy.yaml` 改为创建这三个目录。
|
||
- [ ] 5.3 构建、`openspec validate --all`、`./scripts/context-health.sh`;提交并推送 8-11。
|
||
|
||
## 6. 测试环境验证(AGENTS.md 规定自动化测试为 N/A;按 ENG-TEST-001 在测试环境验证)
|
||
|
||
- [ ] 6.1 审计:部署后 24 小时,审计日增约 300 条(按小时只读统计);人工操作照常写审计;`app.log` 中有 `logger=audit` 的行且不含快照;新对接日志的 `audit_event_id` 可为空。
|
||
- [ ] 6.2 运行时覆盖:把一个机器动作覆盖为 `log_only`,再恢复,确认写入行为随之切换。
|
||
- [ ] 6.3 退款后处理:在测试环境造一张后处理会失败的退款单,确认每次尝试都有记录、退避生效、第 10 次后转人工并写结论审计,人工重试成功后状态变为已完成。
|
||
- [ ] 6.4 停复机:造一条执行前已是目标状态的停机指令,确认写入 `skipped` 记录。
|
||
- [ ] 6.5 采集:成功记录带原始数据,失败记录带错误详情和原始数据,无套餐卡的失败也写入;记录中没有密钥、签名或加密报文。
|
||
- [ ] 6.6 归档:在测试库用一个过期的空分区或小分区执行一次维护,确认生成 `csv.gz` 和 manifest、行数一致后分区被删除;模拟目录不可写时,已摘出的分区仍保留。
|
||
- [ ] 6.7 查询接口:每个接口分别验证查单个、查全部、分页总数和各筛选条件;用 `EXPLAIN` 确认走索引并做了分区裁剪。
|
||
- [ ] 6.8 部署:确认 `/opt/junhong_cmp/api/logs`、`/opt/junhong_cmp/worker/logs`、`/opt/junhong_cmp/worker/archive` 生成且轮换正常,同步服务器能拉到文件。
|
||
|
||
## 7. 归档顺序
|
||
|
||
- [ ] 7.1 本 Change 必须在 `add-card-traffic-queue-and-observed-deduction` 和 `add-carrier-gateway-rate-limit` 归档之后再归档。
|