Files
junhong_cmp_fiber/openspec/specs/operations-audit/spec.md
break 370fd3e67f
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 10m49s
update
2026-09-03 09:28:28 +08:00

136 lines
9.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 运营审计当前行为
## Purpose
描述审计调查、资源活动与审计时间线的当前可观察行为。
## Requirements
### Requirement: 审计时间线
系统 SHALL 支持按事件、操作者、资源、请求、关联标识和资金维度查询已记录的审计事实。新建的 `tb_integration_log` 在已取得稳定审计事件时 SHALL 写入其内部 ID 作为 `audit_event_id`,并且该日志的非空 `integration_id` SHALL 出现在对应事件列表和事件详情的 `investigation_refs.integration_refs` 中;关联生成失败时系统 MUST 保留 Integration Log 并记录可排查告警,且 MUST NOT 按名称、时间或摘要推断关联。历史 Integration Log 不在本要求的回填范围内。审计事件的构造、校验或持久化失败 MUST 记录可关联的结构化错误日志和二次失败记录,且 MUST NOT 改变已通过业务校验的业务操作结果或接口响应。
#### Scenario: 审计时间线
- **GIVEN** 审计事实已存在
- **WHEN** 使用对应维度查询
- **THEN** 返回匹配的事实与稳定动作编码,不用访问日志替代
#### Scenario: 事件返回已关联外部交互引用
- **GIVEN** 一个在线审计事件有 `tb_integration_log.audit_event_id` 指向其内部 ID 的外部交互记录
- **WHEN** 查询全局审计事件列表或该事件详情
- **THEN** 该事件的 `investigation_refs.integration_refs` 返回该记录的 `integration_id`
#### Scenario: 事件没有关联外部交互引用
- **GIVEN** 一个在线审计事件没有稳定关联的外部交互记录
- **WHEN** 查询全局审计事件列表或该事件详情
- **THEN** `investigation_refs.integration_refs` 返回空数组
#### Scenario: 新外部交互日志具有稳定审计关联
- **GIVEN** 系统即将记录一次新的外部调用、入站回调或未发送裁决
- **WHEN** 写入对应 Integration Log
- **THEN** 该记录保存非空 `audit_event_id`,且其目标 Audit Event 已存在
#### Scenario: 缺少审计关联时保留外部交互日志
- **GIVEN** 一次新的外部交互日志没有稳定审计事件关联
- **WHEN** 系统尝试写入该 Integration Log
- **THEN** 系统持久化该 Integration Log、记录可排查告警并返回空 `integration_refs`
#### Scenario: 审计写入失败不阻断业务
- **GIVEN** 一个业务操作已通过自身输入、权限和状态校验
- **WHEN** 该操作的审计事件构造、校验或持久化失败
- **THEN** 系统提交或返回该业务操作原本的结果,并以请求关联标识、动作编码和资源标识记录审计失败
### Requirement: 轮询审计事实保留边界
系统 SHALL 仅为产生业务事实变化、轮询失败、结果未知或人工触发的轮询操作持久化统一审计事件及资源快照。成功且无业务变化的自动轮询 MUST 不创建 `tb_audit_event``tb_audit_event_resource`,审计调查接口仅返回实际已保留的历史事实。
#### Scenario: 自动轮询成功但无业务变化
- **GIVEN** 一次自动轮询成功且没有改变任何业务状态、有效流量或风险结论
- **WHEN** 系统结束该轮询处理
- **THEN** 审计事件和审计资源表不新增该次轮询记录
#### Scenario: 自动轮询改变业务事实
- **GIVEN** 一次自动轮询产生可应用的业务状态或有效流量变化
- **WHEN** 系统提交该变化
- **THEN** 系统保留对应的审计事实与资源快照
### Requirement: 审计归档与日留存受控执行
系统 SHALL 提供独立的审计归档与日留存任务总开关。总开关关闭时,系统 MUST 不调度、不消费且安全跳过已入队的 Audit 日归档、Integration Log 日归档和日志日留存任务,不扫描或修改在线日志表。总开关开启时,每次任务执行 MUST 至多处理一个已结束的上海自然日;维护者可在低峰期重复执行以推进历史积压。
#### Scenario: 归档与留存总开关关闭
- **GIVEN** 审计归档与日留存任务总开关关闭
- **WHEN** 定时器触发或 Worker 取得已入队的归档或留存任务
- **THEN** 系统跳过该任务,不扫描 `tb_audit_event``tb_audit_event_resource``tb_integration_log`,且不创建归档或清理记录
#### Scenario: 总开关开启时处理积压
- **GIVEN** 审计归档与日留存任务总开关开启,且存在多个未处理的已结束自然日
- **WHEN** Worker 执行一次归档或留存任务
- **THEN** 系统至多处理一个自然日,并保留其余日期供后续受控执行
### Requirement: 审计在线数据逐日物理留存
系统 SHALL 以 Asia/Shanghai 已结束的自然日为单位处理统一审计事件及其资源快照的在线留存。每次留存执行 SHALL 从最早尚未完成清理的归档日开始至多处理一个已结束的自然日Integration Log 的 `pending` 记录不得阻断已通过完整性校验的审计事件及资源快照清理。任一审计归档日未通过完整性校验时,系统 MUST 保留该日及其后续日期的在线审计数据,且不得将它们标记为已清理。系统 MUST 先删除该日的审计资源快照,再删除该日的审计事件,并保留对象存储归档对象及清单作为恢复凭证。
#### Scenario: 已验证日期完成物理清理
- **GIVEN** 某已结束自然日的审计归档成功,归档对象和清单可读取且与在线记录范围、数量和校验摘要一致
- **WHEN** 日留存任务处理该日期
- **THEN** 系统分批删除该日在线审计资源快照和审计事件,并将该归档日标记为已清理
#### Scenario: Integration Log pending 不阻断审计清理
- **GIVEN** 某已结束自然日的审计归档已通过完整性校验,且同日存在 pending Integration Log
- **WHEN** 日留存任务处理该日期
- **THEN** 系统仍完成该日在线审计资源快照和审计事件的物理清理
#### Scenario: 归档校验失败阻断连续清理
- **GIVEN** 某尚未清理的归档日缺少归档、归档校验失败或清单与在线数据不一致
- **WHEN** 日留存任务处理该日期
- **THEN** 系统不删除该日或更晚日期的在线审计数据,并将失败信息写入独立日留存日志
#### Scenario: 失败后从未完成日期续跑
- **GIVEN** 日留存任务在某个归档日失败,较早日期已经标记为已清理
- **WHEN** 后续日留存任务再次执行
- **THEN** 系统从最早未完成清理的归档日继续处理,不重复删除已完成日期的数据
### Requirement: 日留存独立运行日志
系统 SHALL 将日留存的日期推进、清理成功和阻断失败写入独立轮转日志。该日志 MUST 位于 Worker 工作目录下配置的 `logs/audit-retention.log`,每条失败记录 MUST 包含归档日期、数据来源、失败分类和安全错误摘要。日留存和日归档路径 MUST NOT 将失败详情写入 `tb_log_archive_run.error_summary`
#### Scenario: 留存日期被阻断
- **GIVEN** 日留存处理某个归档日时发生缺失账本、pending 记录、归档校验或删除错误
- **WHEN** 系统停止该日期推进
- **THEN** `logs/audit-retention.log` 记录该日期、来源、失败分类和错误摘要
- **AND** 对应账本记录的 `error_summary` 不写入该失败详情
#### Scenario: 留存日期清理成功
- **GIVEN** 某归档日通过全部校验并完成在线数据物理删除
- **WHEN** 系统完成该日期处理
- **THEN** `logs/audit-retention.log` 记录归档日期、各来源清理数量和耗时
### Requirement: 审计调查留存边界连续
系统 SHALL 仅将连续完成物理清理的审计归档日期间公开为已归档边界。在线审计调查接口 MUST 继续允许查询任何尚未物理清理的较早日期,且不得因某个较晚日期已归档而将仍在线的日期错误标记为已归档。
#### Scenario: 清理链存在未完成日期
- **GIVEN** 某较早归档日尚未完成清理
- **WHEN** 后续日期的归档已成功生成
- **THEN** 审计调查接口仍将较早未清理日期视为在线可查询数据
## 可达操作索引
本节只用于入口导航,不是行为 Requirement业务义务以上述 Requirements 为准。
### 审计调查
`GET /api/admin/audit/actors/{kind}/{id}/events`(查询操作者行为时间线);`GET /api/admin/audit/correlations/{correlation_id}/timeline`(查询业务关联时间线);`GET /api/admin/audit/events`(查询全局审计事件);`GET /api/admin/audit/events/{event_id}`(查询审计事件详情);`GET /api/admin/audit/finance/timeline`(查询资金调查时间线);`GET /api/admin/audit/integrations`(查询外部集成交互列表);`GET /api/admin/audit/integrations/{integration_id}`(查询外部集成交互详情);`GET /api/admin/audit/integrations/overview`(查询外部集成交互总览);`GET /api/admin/audit/requests/{request_id}/timeline`(查询请求关联时间线);`GET /api/admin/audit/resources/{resource_type}/{resource_id}/timeline`(查询通用资源时间线);`GET /api/admin/audit/resources/search`(精确搜索注册资源);`GET /api/admin/audit/risks/events`(查询风险事件明细);`GET /api/admin/audit/risks/overview`(查询风险调查总览)。
### 资源活动
`GET /api/admin/agent/resource-activities/{resource_type}/{identifier}`(查询代理资源活动);`GET /api/admin/enterprise/resource-activities/{resource_type}/{identifier}`(查询企业资源活动)。