大多数声称有审计追踪的系统,其实只有一个活动日志。这两者的区别,只有在有人提出一个日志答不上来的问题时才会暴露。而在受监管的系统里,这个问题往往带着法律截止日期一起来。

问题不是"发生了什么"。活动日志能回答这个:警报 88214 由用户 412 在 14:32 关闭,原因代码 NO_SAR。但监管要问的是另一件事——那天 14:32 这家机构到底知道什么,是哪条规则版本产生了这条警报,客户的风险评级在随后三次更新之前是什么,以及分析师当时被展示了什么推理依据。

打开网易新闻 查看精彩图片

这些是"重建"要求,没法事后补,因为数据从一开始就没被采集。

"时间点"到底要求什么

四个属性,每一个都有牙齿。

只追加的决策记录。决策记录永不更新,更正是一条引用旧记录的新记录。这听起来理所当然,却经常被 UPDATE cases SET status = ... 这种写法违反,而它摧毁的正是前一状态唯一的副本。

带版本的参考数据。客户风险评级、交易对手分类、国家风险评分、PEP 名单——这些都会变,而且都会影响决策。如果你的客户表只保留当前状态,那么字段第一次变更时,所有历史决策就都变得无法解释。

带版本的控制项。每一条规则、阈值和策略都是可寻址、带版本、带审批记录的对象。决策引用的是产生它的那个控制版本,而不是控制本身。

持久化的模型调用。如果模型参与了建议,那么提示词、检索到的上下文、模型版本标识、参数和原始输出,都要和决策一起留存。

双时态:监管关心的是"你当时知道什么"

可行的模式是双时态。每条记录同时携带有效时间范围(这个事实在现实世界中何时为真)和事务时间范围(系统何时相信它)。监管关心的是后者,因为问题是你知道什么,而不是实际什么是真的。

客户风险评级表可以这样设计:客户 ID、评级、valid_from 与 valid_to 表示何时为真,recorded_from 与 recorded_to 表示我们何时相信它。重建就变成一次查询:recorded_from <= T AND recorded_to > T

最常被跳过的那一项

带版本的控制项,是团队跳过最多的一环。阈值最终落在一张配置表里,运营用户通过一个没有审批流程、没有历史的界面直接编辑。当检查员问去年三月的阈值是多少、谁批准的,诚实的答案是:没人知道。

把推理当作短暂易逝的东西,是当代版的"不记录规则版本"。一个可用的表结构大致长这样:决策 ID、主体类型与主体 ID(警报/客户/报告)、决策时间、决策人(用户或系统主体)、结果、控制版本 ID(外键,不可变)、策略版本 ID(外键,不可变)、输入快照引用(指向物化后的输入状态)、推理引用(人类当时被展示的内容)、模型调用 ID(可空外键)、取代关系。

这些字段里没有一个是事后能补出来的。要么在决策发生的那一刻就写进去,要么两年后面对提问时,你手里只有一个答非所问的活动日志。