重置项目上下文与规范文档

This commit is contained in:
2026-08-07 16:18:07 +08:00
parent 6611ca5226
commit 79e2d9ff92
1900 changed files with 1552 additions and 348365 deletions

View File

@@ -1,166 +0,0 @@
# PRDTECH 全局多视角审计与外部集成追踪
Status: ready-for-agent
---
## Problem Statement
当前系统只有账号操作日志、资产操作日志和手动轮询日志等局部实现。它们的操作者、资源、结果和查询结构不一致,账号与资产审计使用裸 goroutine 写入,进程退出或数据库短暂失败时会丢失;资金、审批、配置和跨模块业务又缺少统一审计。现有记录无法从一次请求、一个业务链路或多个受影响资源串联完整过程。
Gateway、运营商、企业微信和支付等外部交互也没有通用 Integration Log。七月迭代的状态同步、审批和资金处理如果继续各建日志将无法解释“为什么没有请求上游”“哪次回调改变了业务状态”以及“某次资金变化对应哪个审批”。
Access Log 当前只递归脱敏请求体,响应体仍原样记录,登录 Token、个人数据和敏感配置存在泄漏风险回调和文件路由也缺少专门的正文记录策略。
## Solution
一次停机发布切换到四类边界清晰的记录Access Log 负责 HTTP 调试Audit Event 负责不可变业务审计,现有钱包流水/订单/退款等 Domain Ledger 继续作为领域事实Integration Log 负责外部交互和未实际发出的同步尝试。Audit Event 通过资源关系表关联一个操作涉及的多个资源,并用 `request_id/correlation_id/parent_event_id` 串联请求和跨任务业务链路。
本次切换覆盖全部现有敏感写操作:新旧业务统一使用 Audit Writer旧账号、资产和手动轮询审计表停止新增不双写历史数据保留原表并通过 Query 只读投影到新审计中心。切换准备或验证失败则本次版本整体不放量,不能以局部模块继续写旧表作为中间态。
“全部现有敏感写操作”以仓库级《审计覆盖基线》为可验收证据,不以七月迭代需求清单代替。基线必须覆盖所有状态变更、敏感读取、关键拒绝和失败入口,并对 Audit Event、Domain Ledger、Integration Log、Outbox 或 N/A 作出逐入口决定。
## User Stories
1. 作为审计人员,我希望回答谁在什么入口对哪些资源做了什么,结果、风险和前后变化是什么。
2. 作为运维人员,我希望按 `request_id``correlation_id` 查看一次请求或完整业务链路中的审计、任务、外部交互和领域流水。
3. 作为资产运营人员,我希望从卡、设备、退款、订单、钱包等资源查看跨模块时间线,而不被普通无变化轮询淹没。
4. 作为财务人员,我希望资金审计能关联审批、业务单、钱包流水和资产处理,同时明确钱包流水才是金额事实。
5. 作为安全人员,我希望集中查看失败、拒绝、高风险和严重事件,并确保敏感字段默认脱敏。
6. 作为集成运维人员,我希望看到 Gateway、运营商、企微和支付的脱敏请求结果以及合并、限流、提前完成等未发请求原因。
7. 作为历史数据查询者,我希望旧账号、资产和手动轮询记录仍可只读检索,但发布后不再出现新旧两份不一致记录。
8. 作为普通代理或企业用户,我希望只能在原业务详情看到自己有权限资源的脱敏轨迹,不能进入平台全局审计中心。
## Implementation Decisions
### 四类记录的权威边界
- Access Log 存储在现有日志文件/日志平台,只用于 HTTP 调试、性能和 `request_id` 检索,不作为业务事实或业务审计权威。
- Audit Event 存储在 PostgreSQL回答操作者、动作、资源、结果、风险和字段变化。事件创建后不可更新或删除普通读操作不创建 Audit Event敏感读取例外。
- Domain Ledger 继续由钱包流水、订单、退款、充值、企微审批实例、套餐使用记录等业务表承担。审计 Query 可以链接或投影这些记录,但 Audit Event 不替代领域事实。
- Integration Log 存储 Gateway、运营商回调、企微、微信/支付宝及其他外部交互,也记录业务同步尝试在发请求前被 `merged/rate_limited/completed/cancelled` 的解释结果。
- 普通高频轮询成功且状态未变化只写 Integration Log状态变化、人工强制触发、连续失败或高风险异常再写 Audit Event。
- Outbox 和通用异步任务状态是可靠投递/执行事实,不塞入 Audit Event JSON。审计链路 Query 通过稳定 ID 关联它们。
### Audit Event 数据模型
- 新建 `tb_audit_event`,核心字段包括:不可变唯一 `event_id``occurred_at`、类别、动作编码/名称、操作者快照、入口来源、租户/店铺/企业标签、结果、风险、摘要、错误码/摘要、前后数据、元数据、请求/关联/父事件 ID、IP/User-Agent/路径/方法、`content_hash` 和创建时间。
- `result` 为 string 类型:`success/failed/denied/partial``risk_level` 为 string`normal/warning/high/critical`。操作者、来源、类别和动作均使用集中常量或注册表,不允许各 Service 自由拼接 magic string。
- `actor_kind` 至少支持 `admin_user/agent_user/enterprise_user/personal_customer/open_api_account/system_task/carrier_callback/wecom_callback`。系统和回调允许 `actor_id=NULL`,但 `actor_name` 必须是可读快照。
- `source` 表示入口而不是人员,至少支持 `admin_api/personal_api/open_api/asynq/scheduled_job/gateway/carrier_callback.* /wecom_callback/wecom_polling/data_migration`
- 新建 `tb_audit_event_resource`,每个事件可关联多个 `primary/affected/reference` 资源;字段为事件内部 ID、资源类型、可空资源 ID、资源键快照、关系和创建时间。一个事件至少有一个 `primary` 资源。
- 资源关系使用复合唯一索引,资源 ID 和资源键各有时间线索引;不建立数据库外键或 GORM 关联标签。
- `content_hash` 基于脱敏、标准化后的不可变事件内容生成,用于完整性核对,不包含数据库自增 ID。Repository 不提供 Update/Delete 方法。
- `before_data``after_data``metadata` 分别最多 16KB超限时保存截断标志、原字节数、摘要和受控任务/制品引用,批量明细留在对应业务任务表或对象存储。
### 动作注册表与写入可靠性
- 实现 Writer 前先完成全仓审计面盘点。每个 Handler、Application、Service、Worker、定时任务和回调入口都必须登记业务所有者、动作、资源、事务边界、失败策略和确认测试N/A 必须写明理由并经评审。
- 建立 Action Registry定义稳定动作编码、中文名称、类别、默认风险、允许的资源类型和敏感字段规则DTO 枚举说明、筛选项和前端名称都从同一注册表生成。
- 至少覆盖账号/角色/权限、店铺、资产、套餐、钱包/资金、订单/退款/充值、企微、支付与系统配置、数据同步、导入导出及登录安全的本期动作。未经注册的动作不得写入生产审计。
- 钱包余额、人工退款结果、代理钱包回退、线下充值入账、账号角色/权限、支付/企微/关键系统配置、人工卡状态、敏感店铺业务员归属及手工绑定企微审批号等成功事件必须与业务变更同事务 `AppendWithTx`;审计失败则业务事务回滚。
- 旧 MVC Service 未迁移为 DDD 时通过统一 Audit Writer Adapter 接入新模型,不要求为审计一次性重构全部业务;但当前触碰的复杂资金、审批和卡状态用例仍按各自 Spec 迁入 Application/Domain。
- 业务已经回滚的 `failed/denied` 事件使用独立短事务写入,禁止裸 goroutine。该审计再失败时保留原业务错误同时写 `critical` 应用日志和监控指标。
- 异步系统事件与状态变化通过原业务事务或 Outbox 可靠关联,不使用 `go func()`。Asynq/Outbox 载荷必须传递 `event_id/request_id/correlation_id/parent_event_id`
- `request_id` 由现有中间件生成并贯穿同一 HTTP 请求;`correlation_id` 在退款、充值、审批、钱包、卡状态等跨请求业务起点生成并贯穿 Outbox/Asynq/Integration Log`parent_event_id` 表示直接因果,不用于替代 correlation。
- 对全部旧审计调用建立切换清单和自动检查。发布产物中禁止继续调用旧 `account_audit/asset_audit` 写服务或直接 Create 旧日志模型;启动装配不再注入旧 Writer。
- 系统配置更新和 Outbox 人工恢复必须在各自 Application 组合根注入正式 Audit Writer业务事实与审计同事务未装配或审计失败时失败关闭不得回退到空 Adapter、临时表或裸 goroutine。
### Integration Log
- 新建 `tb_integration_log`,至少保存唯一 `integration_id`、provider、方向、operation、外部单号、资源、触发来源/场景/序列/尝试、计划/开始时间、结果、HTTP/渠道码及摘要、脱敏请求响应摘要、耗时、是否改变状态、元数据、请求/关联 ID、可空 Audit Event ID 和创建时间。
- `direction``inbound/outbound``result` 至少支持 `success/failed/not_found/invalid_payload/ignored/merged/rate_limited/completed/cancelled`;实施可增加内部 `pending` 执行态,但公开 DTO 必须返回中文结果名称并保持终态语义明确。
- 一次外部尝试使用稳定 `integration_id`。实际调用前先持久化可恢复的尝试事实,完成后条件更新终态;若发出请求后响应未知,必须记录“结果未知”,不得伪装为普通失败并盲目重发具有副作用的外部请求。
- 数据同步按 UR#94 记录 `trigger_source/scene/series/attempt`;同序列详情一次返回 0/3/5 全部尝试。合并、互斥、限频和已达预期即使没有 HTTP 状态也必须可解释。
- 运营商/支付/企微入站回调先保存脱敏摘要和幂等标识,再进入业务处理;原始加密报文、完整回调正文、签名和附件不进入普通审计详情。
- Integration Log 只保存外部交互事实,不存业务审批/支付/卡状态的权威状态;业务改变时通过 `audit_event_id/correlation_id` 关联。
### 脱敏与 Access Log 修正
- 永不进入 Audit/Integration/Access 正文的数据包括密码、操作密码、验证码、Access/Refresh Token、Secret、回调 Token/EncodingAESKey、支付私钥/公钥原文、完整身份证、对象存储签名 URL、企微 `media_id` 和 Authorization/Cookie。Sanitizer 直接删除或只保留字段存在/长度,不把原值保存成可逆掩码。
- 手机号、IP、ICCID、钱包金额和第三方交易号允许在受控审计存储中作为业务快照但普通 Query 默认脱敏;完整查看需要 `audit:sensitive:view`,导出需要独立 `audit:export` 和字段授权。
- 查看完整敏感值本身写高风险 Audit Event携带被查看事件/资源和操作者;不能因为已有全局查看权限跳过二次审计。
- Access Log 的响应体必须和请求体使用同一递归 Sanitizer再执行 50KB 限制;当前 `truncateBody(c.Response().Body())` 原样记录行为必须移除。
- 路由级策略:登录/Token/支付或企微配置只记字段名和长度;支付、企微、运营商回调只记摘要与哈希;文件上传下载不记文件内容和签名 URL普通 JSON 脱敏后最多 50KB。
- 非 JSON 解析失败不能直接原样记录敏感回调或文件应先应用路由策略和安全文本截断。Query 参数和 Header 同样覆盖 token、secret、sign、nonce、authorization、cookie 等字段。
### 一次性切换与历史投影
- 本需求是经用户确认的全局例外:在同一次停机发布中完成新表/索引、Audit Writer、Integration Writer、现有敏感写入口、Query API 和必要前端切换。不得按模块长期双轨运行。
-`tb_account_operation_log``tb_asset_operation_log``tb_polling_manual_trigger_log` 发布后停止新写入,不删除、不回填新表。数据库权限或运行时写入护栏应使意外旧写尽快暴露,不能静默继续。
- 旧手动轮询日志当前还承担进度状态。切换时其用户可见的手动触发、进度和监控接口保持原契约,但运行状态由七月公共异步任务状态承接,外部尝试由 Integration Log 承接;不得因停写旧表使运维功能消失。
- 历史 Query 使用 `UNION ALL` 把旧账号、资产和手动轮询记录规范化为只读投影,返回 `record_source=legacy_account/legacy_asset/legacy_polling` 和确定性历史事件键;旧记录不伪造不存在的 correlation、风险或多资源关系。
- 现有 `GET /api/admin/assets/{identifier}/operation-logs` 在过渡期保留兼容响应,但读取新 Audit Event 与旧资产投影,不再直接绑定旧表;新前端以全局资源时间线为准。
- 发布门禁要求旧写入口清单为零、新旧 Query 样本对账通过、关键事务审计失败回滚通过、Access Log 脱敏通过。任一失败则在开放流量前整体停止发布。
- 数据迁移全部为增量且可回滚。新系统一旦接收生产写入,已生成 Audit/Integration/Outbox 记录不得删除回滚;应用采用前向修复,不能回到旧 Writer 形成新的分裂历史。
### 查询 API 与权限
- 全局审计中心提供:
- `GET /api/admin/audit/events``/{event_id}`
- `GET /api/admin/audit/actors``/{kind}/{id}/summary``/{kind}/{id}/events`
- `GET /api/admin/audit/resources/search``/{type}/{id}/timeline`
- `GET /api/admin/audit/requests/{request_id}/timeline`
- `GET /api/admin/audit/correlations/{correlation_id}/timeline`
- `GET /api/admin/audit/risks/overview``/events`
- `GET /api/admin/audit/integrations``/{id}`
- `GET /api/admin/audit/finance/timeline`
- `POST /api/admin/audit/exports`
- 所有列表服务端分页,默认 20、最大 100稳定时间+ID排序。公共关键词只匹配已有索引支持的摘要、资源键、操作者和请求 ID不对 JSONB 做无索引模糊扫描。
- 资源搜索先查询业务读模型返回候选 `resource_type/id/key/display_name`,再打开时间线;静态 `/resources/search` 必须先于动态资源路由。`include_related=true` 只展开事件已直接关联资源,不递归遍历图。
- Request Timeline 组合数据库中可关联的 Audit Event、Outbox/任务摘要和 Integration LogAccess Log 仍在文件/日志平台API 只返回事件内已快照的 HTTP 摘要和 `request_id` 日志检索标识,不在请求时扫描本地日志文件。
- Finance Timeline 组合 Audit Event 与钱包流水、订单、退款、充值和企微实例,每条明确 `record_source`;金额结论以 Domain Ledger 为准。
- 权限码至少拆分 `audit:global:view/actor:view/resource:view/request:view/risk:view/integration:view/finance:view/sensitive:view/export`。超级管理员拥有全量;普通平台角色按授权和原数据范围取交集。
- 代理和企业账号不能进入全局、人员、风险、资金全局或外部集成中心在业务详情查看资源轨迹时Query 必须重新执行店铺/企业权限和字段脱敏。前端隐藏 Tab 不是授权边界。
- 审计导出复用统一 Export DataSource创建时快照过滤条件、数据范围、字段授权和脱敏级别敏感查看权限不自动授予敏感导出权限权限解析失败时拒绝而非回退全字段。
### 前端审计中心
- `/operations/audit` 使用工作台式 Tab全局事件、人员行为、资源轨迹、请求/业务链路、资金审计、风险事件、外部集成Tab 和字段以后端权限为准。
- 全局事件表展示时间、风险、操作者、操作、主要资源、来源、结果和 request ID行详情抽屉分为事件摘要、操作者/入口、关联资源、结构化字段差异、请求/业务链路和错误/外部交互。
- 资源轨迹先搜索候选再选择,普通无变化轮询不进入业务时间线;外部集成 Tab 可按 provider、operation、方向、结果、资源、触发来源/场景/序列筛选,并连续展示 0/3/5 尝试。
- 人员、风险、请求和业务链路使用服务端汇总/时间线,不由前端下载全量事件再聚合。第一版不做自动封禁、风险处置工单或自由拖拽关系图。
- 敏感字段默认掩码;有权限用户点击“显示敏感数据”后重新请求受控接口并产生敏感读取审计。无权限、历史字段不存在和数据已按策略删除均使用明确但不泄密的状态。
### 保留、清理与可观测性
- 资金、权限、审批和关键配置 Audit Event 保留 5 年;普通资产/业务 Audit Event 保留 2 年Audit Event 默认不由在线应用删除。
- Integration Log 默认 180 天Gateway 无变化成功记录 30 天,异常或状态变化记录 180 天Access Log 保留 30 天。清理按时间/主键分批执行并记录结果。
- 达到单表维护阈值后按月分区并归档超期分区,本期不为尚未达到阈值预建复杂分区管理,但表和 Query 必须支持后续演进。
- 应用运行账号不提供 Audit Event Update/Delete 能力;归档/清理由独立受控维护身份执行。Integration Log 只允许执行态到终态的受控条件更新,不允许事后改写请求结果。
- 监控 Audit/Integration 写入失败、失败短事务失败、旧表意外新增、Outbox 积压、Integration Log 增长/清理、敏感读取和导出次数。
## Testing Decisions
- 领域/Application 测试覆盖事件不可变、多资源至少一个 primary、动作注册、风险默认值、内容哈希稳定、16KB 截断和禁止字段删除。
- PostgreSQL 集成测试验证唯一/查询索引、关键业务与 Audit Event 同事务、审计写入失败回滚、失败/拒绝短事务、重复事件幂等和资源时间线。
- 对账号、角色权限、资产、套餐、钱包、退款、充值、配置、导入导出、登录安全和手动同步建立切换清单;自动测试或静态检查证明生产装配不再调用旧 Writer旧三表发布后无新增。
- 覆盖基线测试或静态检查证明仓库内全部状态变更、敏感读取、关键拒绝和失败入口均已分类;新增敏感入口未登记、动作未注册或 N/A 缺少理由时门禁失败。
- 公共基础 Adapter 集成测试覆盖系统配置更新和 Outbox 人工恢复的成功同事务、审计失败整体回滚、敏感值不落库、恢复原因与批次留痕以及生产组合根装配。
- 历史投影测试使用旧账号/资产/手动轮询样本,验证 `UNION ALL` 的字段映射、确定性历史键、分页排序、`record_source` 和新旧交界时间无重复/漏项。
- Integration 测试覆盖 outbound 成功/失败/响应未知、inbound 回调、未发送的 merged/rate_limited/completed、同序列 0/3/5、状态变化关联 Audit Event 和重复回调。
- Access Log 测试覆盖嵌套 JSON、数组、非 JSON、登录/Token、支付/企微/运营商回调、上传下载和响应体,证明 Token、Secret、操作密码、签名 URL、Authorization、Cookie 等不落盘且 50KB 生效。
- 权限测试覆盖超级管理员、不同平台角色、代理和企业;验证 Tab、API、字段、资源范围、敏感查看与导出权限相互独立越权资源不泄露存在性。
- Query 性能测试使用代表性事件/资源/Integration 数据,验证分页和常用过滤使用索引、无 JSONB 全表模糊扫描、无资源/操作者 N+1满足项目 P95/P99 目标。
- HTTP 集成测试穿过真实 Fiber 认证、Handler、Query/GORM 和统一错误响应;新 Handler 同步注册两个 OpenAPI 文档生成器并验证静态/动态路由顺序。
- 停机发布演练覆盖暂停 Worker、迁移、旧写护栏、新 Writer 切换、样本对账、恢复 Worker、放量前失败退出和放量后的前向修复已生成审计数据不得通过清表回滚。
- 前端验收覆盖七个视角、权限空态、历史投影、资源候选、request/correlation 跳转、0/3/5 序列、敏感二次查看、导出和错误状态。
## Out of Scope
- 不把 Access Log、Audit Event、Domain Ledger 和 Integration Log 合并成一张万能日志表。
- 不把普通列表、详情和未读数查询全部写成业务审计;只审计敏感读取。
- 不在线回填旧日志到新表,不长期双写新旧审计,不删除旧历史表。
- 不为数据同步另建 `tb_card_sync_execution` 或独立同步审计页面。
- 不把整个旧业务仓库一次性迁成 DDD只统一其审计 Adapter复杂用例按各自需求迁移。
- 不建设自动风控封禁、风险处置工单、自由关系图或实时行为分析平台。
- 不在 API 请求中扫描本地 Access Log 文件,也不把日志文件升级为业务权威存储。
- 不允许应用用户修改/删除 Audit Event不在普通审计详情暴露完整外部报文和密钥。
## Further Notes
- 用户已明确确认一次性全局切换,覆盖标准稿中的“旧写停止、不双写、历史只读投影”口径;这不是可由实现阶段改回渐进双写的建议项。
- 全系统覆盖由 `00-full-audit-surface-inventory.md` 建立基线,系统配置由 `20-system-config-audit-adapter.md` 接入Outbox 恢复由 `21-outbox-recovery-audit-adapter.md` 接入,最终统一由 19 号票验收;后续业务 PRD 也必须增量维护该基线,不能把“公共审计已完成”理解为新业务自动获得审计。
- 当前已核实旧账号/资产审计使用裸 goroutineAccess Log 响应体未脱敏;这两项是发布前必须消除的现存缺陷。
- 当前手动轮询日志兼做进度存储,切断旧表时必须先由公共异步任务状态承接,不得违反 UR#94“轮询管理外部行为保持现状”的确认结论。
- 本需求较大,进入实现前应依据本 Spec 拆成可独立验证的纵向切片,但不得按“先建表、再 Service、再 Handler”的水平层级拆分也不得改变一次停机切换这一最终发布门禁。

View File

@@ -1,18 +0,0 @@
# 00 — 建立全系统审计面与公共能力决策基线
**What to build:** 对整个现有系统而非仅七月迭代执行一次可复核的审计面盘点,形成动作注册表输入和机器可检查的覆盖基线。每个状态变更、敏感读取、关键拒绝或失败入口都必须明确 Audit Event、Domain Ledger、Integration Log、Outbox 的使用决策或给出不适用理由,后续需求以此基线增量维护。
**Blocked by:** None — can start immediately
**Status:** ready-for-agent
**架构通道:** 主通道为 Infrastructure 治理,辅助通道为 Query 验证。
**完整业务边界:** 本票收口 Handler、Application、Domain、Service、Worker 和回调入口的全仓审计分类、动作编码、事务策略、资源关系、失败策略和测试责任人。明确不迁移任何业务代码、不改变已评审业务规则、不把 Access Log、Audit Event、Domain Ledger 和 Integration Log 合并。
- [ ] 盘点全部 HTTP/Worker/定时任务/回调入口,至少覆盖创建、修改、删除、状态流转、资金、权限、关键配置、导入导出、人工恢复、敏感读取、拒绝和关键失败;记录代码入口与业务所有者。(自动扫描候选已生成,待三方确认不存在启发式漏项)
- [ ] 每个入口明确 `Audit Event / Domain Ledger / Integration Log / Outbox / N/A` 决策;选择 N/A 必须写明原因,禁止空白或“以后处理”。(自动分类候选已生成,待三方逐入口评审确认)
- [ ] 对需要审计的入口填写稳定动作编码、中文名称、风险、主要及受影响资源、操作者与来源、前后数据、事务边界、失败策略和自动化测试接缝。(结构已固定,待三方修正并确认业务语义)
- [x] 建立可被静态检查或测试读取的动作注册与覆盖基线,未经登记的新敏感操作不能通过发布门禁。
- [x] 对旧账号、资产、手动轮询 Writer 及全部直接写旧日志表的位置建立准确清单,作为 0409 迁移票和 19 号切换票的输入。
- [ ] 更新《审计覆盖基线》,经业务、研发和安全评审确认不存在未分类入口;评审只确认覆盖与分类,不借机扩大各业务 PRD 范围。

View File

@@ -1,21 +0,0 @@
# 01 — 交付不可变 Audit Event 写入闭环
**What to build:** 业务用例可以通过统一 Audit Writer 写入不可变、多资源、可串联且默认脱敏的审计事件。成功事件能够与业务事实共用事务,失败或拒绝事件使用独立短事务保留;未注册动作、缺少主要资源或审计写入失败时按明确策略阻止错误事实落地。
**Blocked by:**
- 00 — 建立全系统审计面与公共能力决策基线
- `.scratch/tech-public-foundation/issues/01-public-migration-ownership-and-gates.md` — 01 — 建立公共迁移所有权与检查门禁
**Status:** ready-for-agent
**架构通道:** 主通道为 Application + Port/Adapter辅助通道为 Infrastructure。
**完整业务边界:** 本票收口 Audit Event、事件资源、动作注册表、统一 Sanitizer、内容哈希、大小控制和 Writer 可靠性,并用一个代表性敏感写操作验证公开接缝。明确不迁移其他旧 Service不提供完整审计查询中心不用 Audit Event 替代领域流水。
- [ ] Audit Event 支持稳定事件 ID、操作者与入口快照、结果、风险、前后数据、请求/关联/父事件 ID、HTTP 摘要、内容哈希和创建时间;事件资源支持 `primary/affected/reference`,且每个事件至少包含一个 `primary`
- [ ] 动作注册表集中定义稳定动作编码、中文名称、类别、默认风险、允许资源类型和敏感字段规则;未经注册的动作不能写入生产审计。
- [ ] 统一 Sanitizer 删除禁止字段;`before_data``after_data``metadata` 分别执行 16KB 上限,超限后保存截断标志、原字节数、摘要和受控制品引用。
- [ ] `content_hash` 基于脱敏、标准化后的不可变内容生成,不包含数据库自增 ID相同内容哈希稳定Repository 不提供 Update/Delete 能力。
- [ ] `AppendWithTx` 与业务事实使用同一 GORM 事务,任一步失败整体回滚;已经回滚的 `failed/denied` 使用独立短事务,二次失败保留原业务错误并产生 critical 日志和指标。
- [ ] 真实 PostgreSQL 集成测试覆盖不可变约束、多资源、动作注册、风险默认值、哈希、截断、禁止字段、重复事件幂等和事务回滚。

View File

@@ -1,18 +0,0 @@
# 02 — 交付可恢复的 Integration Log 尝试闭环
**What to build:** 外部调用和未实际发出的同步尝试都能以稳定 Integration ID 建立可恢复事实,并通过受控条件更新进入明确终态。入站回调在业务处理前保存脱敏摘要和幂等标识,出站响应未知时保留未知结论而不伪装成普通失败。
**Blocked by:** `.scratch/tech-public-foundation/issues/01-public-migration-ownership-and-gates.md` — 01 — 建立公共迁移所有权与检查门禁
**Status:** completed
**架构通道:** 主通道为 Infrastructure辅助通道为 Application + Port/Adapter。
**完整业务边界:** 本票收口 Integration Log 模型、Writer、执行态到终态的条件更新、入站摘要和未发送结果语义。明确不接管 Gateway、支付、企微或运营商的业务状态机不把外部交互记录作为业务权威状态。
- [x] Integration Log 支持 provider、方向、operation、外部单号、资源、触发来源/场景/序列/尝试、计划与开始时间、结果、渠道摘要、脱敏请求响应摘要、耗时、状态变化标志和关联 ID。
- [x] 方向固定为 `inbound/outbound`;公开终态至少覆盖成功、失败、未找到、无效载荷、忽略、合并、限频、提前完成和取消,并返回对应中文名称。
- [x] 实际外部调用前持久化稳定尝试身份,完成后使用预期状态条件更新;并发完成、重复回调或重复消费不能改写既有终态。
- [x] 请求已发出但响应未知时记录明确的未知结论和恢复策略,不自动把具有副作用的请求当成普通失败盲目重发。
- [x] 入站回调先保存脱敏摘要、内容哈希和幂等标识;原始密文、完整正文、签名、附件和密钥不进入普通记录。
- [x] PostgreSQL 集成测试覆盖出站成功、明确失败、响应未知、未发送终态、入站回调、重复回调、条件更新冲突和 Audit Event 关联。

View File

@@ -1,21 +0,0 @@
# 03 — 完成 Access Log 全路由敏感信息防泄漏
**What to build:** 当前项目所有敏感 HTTP 路由均使用统一的请求、响应、Query 和 Header 脱敏及路由级安全摘要策略。即使正文不是 JSON、解析失败或属于文件载荷也不会把可复用凭证、完整回调或文件内容写入 Access Log。
**Blocked by:**
- `.scratch/tech-public-foundation/issues/09-access-log-recursive-redaction.md` — 09 — 统一 Access Log 请求与响应递归脱敏
- `.scratch/tech-public-foundation/issues/10-sensitive-route-safe-summaries.md` — 10 — 为敏感接口提供安全摘要策略
**Status:** completed
**架构通道:** Infrastructure。
**完整业务边界:** 本票将公共 Access Log 安全能力应用到当前仓库真实路由并建立固定回归矩阵。明确不修改业务响应,不创建审计事实,不把 Access Log 升级为业务权威存储。
- [x] 登录、Token、支付与企微配置路由只记录字段存在性、长度和安全结果不记录密码、验证码、Token、Secret、密钥或完整配置值。
- [x] 支付、企微和运营商回调只记录事件类型、安全资源标识、大小、内容类型、摘要哈希与处理结果,不记录密文、完整正文、签名或附件。
- [x] 上传、下载和导出路由不记录文件字节、Base64、multipart 正文、临时凭证或签名 URL只保留脱敏文件元数据和任务标识。
- [x] Query 和 Header 覆盖 token、secret、sign、nonce、authorization、cookie 等大小写变体;请求和响应均先脱敏再执行 50KB 截断。
- [x] 非 JSON、XML、表单、二进制及解析失败场景均按路由策略安全降级不能回退记录原文。
- [x] 真实 Fiber 测试捕获最终 Access Log覆盖敏感路由矩阵并断言测试凭证、操作密码、回调原文、签名 URL、Authorization 和 Cookie 均未落盘。

View File

@@ -1,18 +0,0 @@
# 04 — 迁移账号、角色与权限敏感操作到统一审计
**What to build:** 账号、角色和权限敏感操作通过统一 Audit Writer 记录操作者、动作、目标资源、结果、风险和前后变化。关键成功审计与业务修改同事务,拒绝和失败审计可可靠保留,这些入口不再调用旧账号审计 Writer。
**Blocked by:** 01 — 交付不可变 Audit Event 写入闭环
**Status:** ready-for-agent
**架构通道:** 主通道为简单写 Application辅助通道为旧 MVC Adapter。
**完整业务边界:** 本票收口现有账号、角色和权限敏感写入口的统一审计接入。明确不重构整个账号模块,不迁移无关读取,不删除或回填旧账号历史表。
- [ ] 账号创建、修改、启停、删除、角色分配及权限变更使用注册动作和统一资源类型,成功、拒绝和失败语义明确。
- [ ] 账号角色或权限关键成功事件与业务事实使用同一 GORM 事务;审计失败时业务修改回滚。
- [ ] 权限拒绝与业务失败通过独立短事务记录,不向客户端泄露底层错误或资源是否存在。
- [ ] 事件包含操作者与入口快照、请求/关联标识、变更前后事实和直接受影响资源,敏感字段按统一规则删除或脱敏。
- [ ] 生产装配中的上述入口不再调用旧账号审计 Service也不直接创建旧账号日志模型静态检查和真实用例测试可证明该边界。
- [ ] 测试覆盖事务成功、审计失败回滚、拒绝、业务失败、重复请求和数据权限边界,不改变旧历史查询结果。

View File

@@ -1,18 +0,0 @@
# 05 — 迁移卡资产生命周期操作到统一审计
**What to build:** 卡分配、回收、删除、停复机、实名策略和状态变化等资产生命周期操作统一产生可关联的 Audit Event并以多资源关系表达卡、设备、店铺、订单等直接影响对象。复杂卡状态规则仍由完整业务用例收口不在审计 Adapter 中复制。
**Blocked by:** 01 — 交付不可变 Audit Event 写入闭环
**Status:** ready-for-agent
**架构通道:** 复杂卡状态用例采用 Application/Domain其他入口采用旧 MVC Adapter。
**完整业务边界:** 本票迁移现有卡资产生命周期写入口的审计能力。明确不重新设计周期轮询、队列、卡资格或重排策略,不迁移本需求未触碰的资产规则,不删除旧资产历史表。
- [ ] 卡分配、回收、删除、手工停复机、实名策略和业务状态变化均映射到已注册动作,成功、拒绝和失败结果保持一致。
- [ ] 事件至少关联一个主要卡资源,并按实际影响关联设备、来源/目标店铺、订单或其他直接资源;不递归制造资源关系。
- [ ] 关键状态变更成功审计与业务事实同事务;失败或拒绝使用独立短事务,重复状态请求不制造重复业务副作用或虚假变化。
- [ ] `request_id/correlation_id/parent_event_id` 在 HTTP、业务用例和后续异步链路中按各自职责传播。
- [ ] 当前卡资产入口不再调用旧资产审计 Writer 或直接创建旧资产日志模型,但兼容历史读取仍可工作。
- [ ] 测试覆盖权限拒绝、状态条件更新、事务回滚、多资源时间线、敏感 ICCID 默认脱敏和重复请求。

View File

@@ -1,18 +0,0 @@
# 06 — 迁移设备与资产导入操作到统一审计
**What to build:** 设备分配、回收、绑定、控制操作以及卡和设备导入任务通过统一 Audit Writer 留下稳定、脱敏、可检索的事件。批量操作只在事件中保存命令摘要和计数,逐项明细继续由业务任务或受控制品承担。
**Blocked by:** 01 — 交付不可变 Audit Event 写入闭环
**Status:** ready-for-agent
**架构通道:** 主通道为简单写 Application/旧 MVC Adapter辅助通道为 Infrastructure。
**完整业务边界:** 本票收口设备生命周期与现有资产导入入口的审计接入。明确不重构整个设备 Service不建立通用批量任务表不把大批量明细塞入 Audit Event JSON。
- [ ] 设备分配、回收、系列绑定、绑卡/解绑、停复机、限速、WiFi 设置、切卡、重启和恢复出厂映射为注册动作。
- [ ] 卡和设备导入任务创建、完成与失败事件关联任务、操作者、来源文件安全摘要和结果计数,不保存文件内容、签名 URL 或完整逐项数据。
- [ ] 批量事件超过大小限制时记录截断元数据、原始计数、摘要及受控任务/制品引用,查询仍能定位权威明细。
- [ ] 关键业务修改与成功审计同事务;拒绝和失败可靠保留,重复任务或重复控制请求不制造重复成功事件。
- [ ] 相关生产入口不再调用旧资产审计 Writer自动检查覆盖直接旧模型 Create 和隐藏装配注入。
- [ ] 真实用例测试覆盖单项与批量、事务回滚、部分结果摘要、多资源关系、权限范围和敏感字段删除。

View File

@@ -1,18 +0,0 @@
# 07 — 迁移店铺、套餐和关键配置操作到统一审计
**What to build:** 店铺敏感归属、套餐管理以及支付、企微和关键系统配置的现有写操作统一记录注册动作、操作者、目标资源和前后变化。关键配置与权限相关成功审计和业务事实同事务,敏感配置原值永不进入审计正文。
**Blocked by:** 01 — 交付不可变 Audit Event 写入闭环
**Status:** ready-for-agent
**架构通道:** 主通道为简单写 Application辅助通道为旧 MVC Adapter。
**完整业务边界:** 本票迁移当前已有店铺、套餐和关键配置敏感入口。明确不接管各业务 PRD 尚未实现的状态机,不主动迁移无关 CRUD不创建配置专用审计表。
- [ ] 店铺敏感业务员归属、关键账号关联和其他已识别敏感变更使用稳定动作及店铺/人员资源关系。
- [ ] 套餐创建、修改、上下架、授权或其他已存在敏感管理入口记录业务命令摘要和直接受影响资源。
- [ ] 支付、企微及关键系统配置变更只记录 Key、安全类型与脱敏前后摘要不保存 Secret、Token、EncodingAESKey、私钥、公钥原文或签名材料。
- [ ] 关键配置和权限相关成功审计与业务事实同事务;拒绝、校验失败和持久化失败按公共失败策略记录。
- [ ] 相关旧账号/资产审计调用与零散配置日志不再承担这些操作的权威审计,生产装配可被自动检查验证。
- [ ] 测试覆盖配置审计失败回滚、店铺越权、套餐批量摘要、敏感字段删除、重复更新和统一中文错误。

View File

@@ -1,21 +0,0 @@
# 08 — 迁移现有资金与订单敏感操作到统一审计
**What to build:** 当前钱包变更、充值、退款和订单资金敏感操作通过统一 Audit Event 关联业务单、钱包、钱包流水、操作者和完整业务链路。金额结论继续以 Domain Ledger 为准,关键成功审计与资金事实同事务且只产生一次。
**Blocked by:**
- 01 — 交付不可变 Audit Event 写入闭环
- `.scratch/tech-public-foundation/issues/02-transactional-public-outbox-write.md` — 02 — 在业务事务中可靠写入公共 Outbox
**Status:** ready-for-agent
**架构通道:** 主通道为复杂写 Application/Domain辅助通道为 Port/Adapter。
**完整业务边界:** 本票迁移仓库当前存在的钱包、充值、退款和订单资金敏感入口,完整收口所触碰用例的金额、并发、幂等和可靠事件边界。明确不用 Audit Event 替代钱包流水、订单或退款事实,不重写未触碰资金用例。
- [ ] 钱包余额变更、代理钱包回退、线下充值入账、人工退款结果及现有订单资金操作使用注册动作和稳定 correlation。
- [ ] Audit Event 关联审批或业务单、钱包、钱包流水及直接受影响资产;每条投影明确领域流水才是金额权威。
- [ ] 余额、流水、成功审计和必要 Outbox 在同一 GORM 事务内提交;审计或 Outbox 写入失败时资金事实整体回滚。
- [ ] 状态条件更新、钱包版本或稳定业务键保证重复请求、Worker 重投和并发处理不重复改变余额、流水或成功审计。
- [ ] 明确失败、拒绝和结果异常使用独立短事务记录安全摘要,不把第三方支付密钥、完整凭证或底层错误返回客户端。
- [ ] PostgreSQL 集成测试覆盖正常资金变化、审计失败、Outbox 失败、乐观锁冲突、重复业务键、并发处理和金额事实对账。

View File

@@ -1,24 +0,0 @@
# 09 — 承接手动轮询状态并记录同步外部尝试
**What to build:** 现有手动触发、进度和监控接口保持用户契约但运行状态由公共异步任务契约承接Gateway 实际请求及合并、互斥、限频、提前完成等未发送尝试进入 Integration Log只有状态变化、人工强制、连续失败或高风险异常进入 Audit Event。
**Blocked by:**
- 01 — 交付不可变 Audit Event 写入闭环
- 02 — 交付可恢复的 Integration Log 尝试闭环
- `.scratch/tech-public-foundation/issues/02-transactional-public-outbox-write.md` — 02 — 在业务事务中可靠写入公共 Outbox
- `.scratch/tech-public-foundation/issues/03-outbox-at-least-once-delivery.md` — 03 — 完成 Outbox 到 Asynq 的至少一次投递闭环
- `.scratch/tech-public-foundation/issues/06-unified-async-task-contract.md` — 06 — 冻结统一异步任务五态和查询契约
**Status:** ready-for-agent
**架构通道:** 主通道为 Application + Infrastructure辅助通道为 Query。
**完整业务边界:** 本票收口旧手动轮询日志承担的运行状态替代、外部尝试记录和兼容接口。明确不改变轮询配置、间隔、Redis 分片队列、任务类型、卡级开关、并发控制或失败重排,不新建同步专用运行表。
- [ ] 手动触发、进度与监控公开契约继续可用,状态、计数、失败摘要和恢复行为映射到公共异步任务五态。
- [ ] 实际 Gateway 请求在调用前建立 Integration Log完成后记录结果、耗时、状态变化和脱敏上游摘要。
- [ ] 合并、互斥、限频、已达预期和取消即使未产生 HTTP 请求也有可解释终态,不伪造 HTTP 状态。
- [ ] 同步序列传播 `request_id/correlation_id/series_id/attempt`同序列查询可连续看到立即、3 分钟、5 分钟的全部尝试。
- [ ] 普通无变化成功只写 Integration Log状态变化、人工强制、连续失败或高风险异常按注册规则关联 Audit Event。
- [ ] 回归测试固定现有轮询配置、队列、开关和监控基线,验证切换前后调度事实不变且旧手动轮询表不再承担新增运行状态。

View File

@@ -1,18 +0,0 @@
# 10 — 提供旧审计历史统一只读投影
**What to build:** 审计查询可以把旧账号、旧资产和旧手动轮询记录规范化为统一只读历史事件,并与新 Audit Event 稳定分页排序。现有资产操作日志兼容接口继续可用,但不再直接绑定旧资产日志表。
**Blocked by:** 01 — 交付不可变 Audit Event 写入闭环
**Status:** ready-for-agent
**架构通道:** Query。
**完整业务边界:** 本票收口三个旧历史来源的 `UNION ALL` 投影、确定性历史键和资产兼容读取。明确不在线回填新表,不修改或删除旧记录,不伪造历史中不存在的 correlation、风险或多资源关系。
- [ ] 旧账号、资产和手动轮询记录分别返回 `legacy_account/legacy_asset/legacy_polling` 来源及确定性历史事件键。
- [ ] 字段映射保留可证明的操作者、操作、资源、结果、时间和摘要;不存在的关联、风险或资源关系显式为空而非推测填充。
- [ ] 新旧记录使用稳定时间加 ID/历史键排序,分页跨越切换时间时无重复、漏项或顺序漂移。
- [ ] 资产操作日志兼容接口同时读取新 Audit Event 与旧资产投影,并保持原业务调用方所需响应兼容性。
- [ ] Query 不返回可用于业务写入的聚合对象,不对旧 JSON 做无索引模糊扫描,不产生 N+1 查询。
- [ ] PostgreSQL 投影测试覆盖三类历史样本、字段映射、确定性键、分页排序、新旧交界和兼容接口。

View File

@@ -1,23 +0,0 @@
# 11 — 交付全局事件和资源轨迹查询闭环
**What to build:** 获得授权的平台用户可以分页查看全局审计事件与详情,先搜索业务资源候选,再打开包含新事件和历史投影的资源时间线。资源权限与字段脱敏由后端重新校验,代理或企业用户只能在原业务范围查看允许的资源轨迹。
**Blocked by:**
- 01 — 交付不可变 Audit Event 写入闭环
- 05 — 迁移卡资产生命周期操作到统一审计
- 06 — 迁移设备与资产导入操作到统一审计
- 10 — 提供旧审计历史统一只读投影
**Status:** ready-for-agent
**架构通道:** Query。
**完整业务边界:** 本票收口事件列表/详情、资源候选搜索和资源时间线 API 及权限、分页、索引和 DTO 投影。明确不递归遍历资源图,不扫描 JSONB不通过聚合根读取不实现其他审计视角。
- [ ] 事件列表和详情支持注册动作、操作者、来源、结果、风险、时间、资源和请求标识等有索引过滤,默认 20、最大 100并稳定按时间与 ID 排序。
- [ ] 资源搜索先查询业务读模型返回类型、ID、Key 和显示名;静态搜索路由先于动态资源路由注册。
- [ ] 资源时间线组合新 Audit Event 和旧投影,`include_related=true` 只展开事件直接关联资源,不递归遍历关系图。
- [ ] 超级管理员、平台角色、代理和企业按权限码与原数据范围取交集;越权查询不泄露资源是否存在。
- [ ] DTO 默认脱敏并返回结果、风险等中文名称;公共关键词不对 JSONB 执行无索引模糊扫描。
- [ ] 真实 Fiber、认证、GORM 和 PostgreSQL 测试覆盖路由顺序、分页、筛选、权限、历史交界、无 N+1 和常用查询索引;新增 Handler 同步两个文档生成器。

View File

@@ -1,21 +0,0 @@
# 12 — 交付人员行为和风险事件查询闭环
**What to build:** 获得相应权限的平台用户可以查看操作者列表、行为摘要、个人事件时间线以及风险概览和风险事件列表。所有聚合均由服务端完成,并严格隔离代理、企业和无对应权限的平台角色。
**Blocked by:**
- 04 — 迁移账号、角色与权限敏感操作到统一审计
- 11 — 交付全局事件和资源轨迹查询闭环
**Status:** ready-for-agent
**架构通道:** Query。
**完整业务边界:** 本票收口人员与风险两个读取视角、服务端汇总和权限边界。明确不建设自动封禁、风险处置工单、实时行为分析或前端全量下载聚合。
- [ ] 操作者查询支持 actor kind、稳定 ID、名称快照、入口、动作、结果、风险和时间过滤并提供摘要及稳定分页事件时间线。
- [ ] 风险概览按风险等级、结果、类别、动作和时间窗口进行有索引汇总,风险事件列表可进一步检索详情。
- [ ] `audit:actor:view``audit:risk:view` 独立授权;代理和企业账号不能进入人员或风险全局视角。
- [ ] 平台角色的权限与数据范围取交集,失败、拒绝、高风险和严重事件不会因缺失可选关联而被错误过滤。
- [ ] 汇总使用服务端 SQL 和批量投影,不下载全量事件、不对 JSONB 模糊扫描、不产生操作者或资源 N+1。
- [ ] HTTP 与性能测试覆盖超级管理员、不同平台角色、代理、企业、空态、筛选空态及代表性数据量OpenAPI 文档同步更新。

View File

@@ -1,24 +0,0 @@
# 13 — 交付请求、业务链路和外部集成时间线
**What to build:** 运维人员可以按 request ID 或 correlation ID 查看同一请求或完整业务链路中的 Audit Event、Integration Log、Outbox 和异步任务摘要,并可按外部提供方、操作、方向、结果、资源、场景和序列检索外部尝试。
**Blocked by:**
- 02 — 交付可恢复的 Integration Log 尝试闭环
- 09 — 承接手动轮询状态并记录同步外部尝试
- 11 — 交付全局事件和资源轨迹查询闭环
- `.scratch/tech-public-foundation/issues/02-transactional-public-outbox-write.md` — 02 — 在业务事务中可靠写入公共 Outbox
- `.scratch/tech-public-foundation/issues/06-unified-async-task-contract.md` — 06 — 冻结统一异步任务五态和查询契约
**Status:** ready-for-agent
**架构通道:** Query。
**完整业务边界:** 本票收口请求时间线、关联时间线和 Integration Log 列表/详情查询。明确不在 API 请求中扫描本地 Access Log不复制 Outbox/任务完整载荷,不把外部交互结果解释成业务权威状态。
- [ ] Request Timeline 组合可关联的审计事件、外部尝试、Outbox 和任务安全摘要,并返回 Access Log 检索标识而不读取日志文件。
- [ ] Correlation Timeline 以稳定 correlation 串联跨请求、回调和异步处理,`parent_event_id` 只表达直接因果,不替代 correlation。
- [ ] Integration 查询支持 provider、operation、方向、结果、资源、触发来源、场景、序列、尝试和时间过滤列表默认 20、最大 100。
- [ ] 同一同步序列能够按尝试顺序连续展示立即、3 分钟、5 分钟结果,包括合并、限频和提前完成等未发送终态。
- [ ] 原始外部正文、密文、签名、附件、Outbox 载荷和任务敏感失败明细不进入普通查询 DTO。
- [ ] 真实链路测试覆盖单请求、多请求 correlation、异步传播、重复尝试、0/3/5 序列、权限隔离和常用查询索引OpenAPI 文档同步更新。

View File

@@ -1,21 +0,0 @@
# 14 — 交付资金审计时间线
**What to build:** 财务人员可以按业务单、钱包、审批、资产和时间查看组合时间线,统一展示 Audit Event、钱包流水、订单、退款、充值和审批实例并清楚区分每条记录来源及金额权威。
**Blocked by:**
- 08 — 迁移现有资金与订单敏感操作到统一审计
- 13 — 交付请求、业务链路和外部集成时间线
**Status:** ready-for-agent
**架构通道:** Query。
**完整业务边界:** 本票收口资金审计的只读组合投影、权限、分页和对账语义。明确不通过查询修改资金状态,不把 Audit Event 当作金额账本,不迁移未触碰的资金写用例。
- [ ] 时间线组合 Audit Event、钱包流水、订单、退款、充值和审批实例每条返回明确 `record_source`、时间、业务标识和安全摘要。
- [ ] 金额、余额和资金结论始终取自 Domain Ledger审计事件只解释操作者、动作、风险、前后变化和关联关系。
- [ ] 支持钱包、店铺、业务单、审批、资产、动作、结果、风险和时间等有索引过滤,并使用稳定时间加来源 ID 排序。
- [ ] `audit:finance:view` 独立授权,代理和企业不能进入全局资金视角;平台角色权限与原资金数据范围取交集。
- [ ] 金额、手机号、第三方交易号等字段默认按权限脱敏,不因某条关联缺失泄露其他资源存在性。
- [ ] 对账和性能测试覆盖多来源同链路、退款与充值、审批关联、无重复漏项、无 N+1 和代表性数据量OpenAPI 文档同步更新。

View File

@@ -1,22 +0,0 @@
# 15 — 交付敏感值二次查看与自审计闭环
**What to build:** 审计详情默认返回掩码或安全状态;具有独立敏感查看权限的用户可以针对明确事件或资源二次请求允许展示的完整值,而该查看行为本身会产生高风险 Audit Event并保留被查看对象、操作者和请求链路。
**Blocked by:**
- 01 — 交付不可变 Audit Event 写入闭环
- 11 — 交付全局事件和资源轨迹查询闭环
- 12 — 交付人员行为和风险事件查询闭环
**Status:** ready-for-agent
**架构通道:** 主通道为 Query辅助通道为简单写 Application。
**完整业务边界:** 本票收口敏感字段受控读取、字段级授权和读取自审计。明确不恢复已被策略删除的原值,不允许超级管理员绕过二次审计,不授予导出权限。
- [ ] 普通详情对手机号、IP、ICCID、钱包金额和第三方交易号等受控字段默认脱敏禁止字段始终不可恢复。
- [ ] 二次查看要求 `audit:sensitive:view`、明确目标和字段范围,并重新校验平台角色、数据范围与资源权限。
- [ ] 成功或被拒绝的敏感查看产生注册的高风险 Audit Event关联被查看事件/资源、操作者、入口和 request ID。
- [ ] 审计写入失败时敏感值不返回;重复查看每次都保留独立读取事实,不因已有全局权限跳过。
- [ ] 无权限、历史字段不存在、原值已删除和资源越权返回明确但不泄密的统一错误或状态。
- [ ] 真实 Fiber 和 PostgreSQL 测试覆盖授权查看、越权、审计失败、禁止字段、历史缺失、并发请求及自审计事件查询OpenAPI 文档同步更新。

View File

@@ -1,24 +0,0 @@
# 16 — 交付审计导出与字段授权快照
**What to build:** 获得审计导出权限的用户可以从支持的审计视角创建异步导出任务。任务创建时固化过滤条件、数据范围、字段授权和脱敏等级,后续角色变更或任务重试不会扩大导出内容。
**Blocked by:**
- 11 — 交付全局事件和资源轨迹查询闭环
- 12 — 交付人员行为和风险事件查询闭环
- 13 — 交付请求、业务链路和外部集成时间线
- 14 — 交付资金审计时间线
- 15 — 交付敏感值二次查看与自审计闭环
**Status:** ready-for-agent
**架构通道:** 主通道为 Query + Export DataSource辅助通道为 Application。
**完整业务边界:** 本票收口审计导出 Scene、字段能力、权限快照、异步任务和导出审计。明确不创建第二套导出框架不把敏感查看权限等同敏感导出权限不在权限解析失败时回退全字段。
- [ ] 审计导出复用统一 Export DataSource 和任务契约,支持经批准的事件、资源、链路、集成、风险和资金过滤条件。
- [ ] 创建任务时快照操作者、权限、数据范围、字段集合、脱敏等级和过滤条件Worker 只使用快照执行。
- [ ] `audit:export``audit:sensitive:view` 独立;导出完整敏感字段需要额外字段授权,解析失败一律拒绝。
- [ ] 文件不包含禁止字段、完整外部报文、密钥、签名 URL 或未授权业务数据;下载继续遵守安全摘要和临时访问策略。
- [ ] 创建、完成、失败和下载等敏感导出行为产生统一 Audit Event并能关联导出任务与请求链路。
- [ ] 测试覆盖权限快照、角色变更、字段空集、敏感权限分离、任务重试、导出审计、越权和文件内容检查。

View File

@@ -1,21 +0,0 @@
# 17 — 交付审计保留、清理和运行监控
**What to build:** 运维人员可以观察 Audit/Integration 写入、旧表意外新增、Integration Log 增长与清理、敏感读取和导出,并由受控维护身份按保留策略分批清理可清理记录。在线应用始终不能更新或删除 Audit Event。
**Blocked by:**
- 01 — 交付不可变 Audit Event 写入闭环
- 02 — 交付可恢复的 Integration Log 尝试闭环
**Status:** ready-for-agent
**架构通道:** 主通道为 Infrastructure辅助通道为 Query。
**完整业务边界:** 本票收口保留分类、Integration Log 分批清理、权限边界、指标与告警。明确不由在线应用删除 Audit Event不预建尚无必要的复杂分区系统不清理已有生产审计事实作为回滚手段。
- [ ] 审计事件按资金/权限/审批/关键配置与普通资产/业务分类表达 5 年或 2 年保留策略,在线应用账号无 Update/Delete 能力。
- [ ] Integration Log 默认保留 180 天Gateway 无变化成功记录保留 30 天;清理按稳定时间与主键小批量执行并记录结果。
- [ ] 清理只允许受控维护身份执行,使用条件范围和可恢复进度,不影响异常、状态变化或仍被业务链路引用的记录。
- [ ] 指标和告警覆盖 Audit/Integration 写入失败、失败短事务失败、旧三表意外新增、Outbox 积压、Integration 增长/清理、敏感读取和导出次数。
- [ ] 日志与指标标签只使用安全 ID、结果和计数不包含正文、敏感值或高基数未受控载荷。
- [ ] 测试覆盖保留边界、分批重跑、并发清理、在线账号拒绝、旧表新增告警和不删除未到期/受保护记录。

View File

@@ -1,25 +0,0 @@
# 18 — 冻结审计中心跨仓前端契约与验收包
**What to build:** 前端仓库获得稳定、框架无关的审计工作台契约和可执行验收数据,能够实现全局事件、人员行为、资源轨迹、请求/业务链路、资金审计、风险事件和外部集成七个视角,并正确处理权限、敏感查看、导出、空态与错误状态。
**Blocked by:**
- 11 — 交付全局事件和资源轨迹查询闭环
- 12 — 交付人员行为和风险事件查询闭环
- 13 — 交付请求、业务链路和外部集成时间线
- 14 — 交付资金审计时间线
- 15 — 交付敏感值二次查看与自审计闭环
- 16 — 交付审计导出与字段授权快照
**Status:** ready-for-agent
**架构通道:** Query/API 契约。
**完整业务边界:** 本票收口跨仓页面、状态、权限和验收契约以及 OpenAPI/样本数据。当前仓库不含前端源码,明确不虚构组件目录、状态库或技术栈,不在本票实现前端页面。
- [ ] 契约覆盖 `/operations/audit` 七个视角、权限控制 Tab、服务端筛选分页、稳定 URL 参数和详情抽屉字段分组。
- [ ] 资源轨迹定义先搜索候选再查看时间线;请求与 correlation 可相互跳转Integration 序列连续展示立即、3 分钟、5 分钟尝试。
- [ ] 敏感字段默认掩码,二次查看重新请求受控接口;导出、敏感查看和各视角权限分别处理。
- [ ] 明确定义加载、真实空态、筛选空态、403、404/不可见、失败重试、历史字段不存在和数据已删除等状态。
- [ ] 提供不含真实敏感数据的七视角验收样本、权限矩阵和人工验收清单,后端 OpenAPI 与真实路由保持一致。
- [ ] 文档明确前端隐藏不是授权边界,第一版不实现自动封禁、风险工单或自由拖拽关系图。

View File

@@ -1,41 +0,0 @@
# 19 — 执行一次性审计切换与停机发布门禁
**What to build:** 发布负责人可以在一次停机窗口内完成新结构、Writer、现有敏感入口、历史查询、权限、监控和跨仓契约切换并通过自动化门禁决定是否开放流量。任一关键检查失败时整体停止发布一旦新系统产生生产事实只能前向修复不能恢复旧 Writer 制造分裂历史。
**Blocked by:**
- 00 — 建立全系统审计面与公共能力决策基线
- 03 — 完成 Access Log 全路由敏感信息防泄漏
- 04 — 迁移账号、角色与权限敏感操作到统一审计
- 05 — 迁移卡资产生命周期操作到统一审计
- 06 — 迁移设备与资产导入操作到统一审计
- 07 — 迁移店铺、套餐和关键配置操作到统一审计
- 08 — 迁移现有资金与订单敏感操作到统一审计
- 09 — 承接手动轮询状态并记录同步外部尝试
- 10 — 提供旧审计历史统一只读投影
- 11 — 交付全局事件和资源轨迹查询闭环
- 12 — 交付人员行为和风险事件查询闭环
- 13 — 交付请求、业务链路和外部集成时间线
- 14 — 交付资金审计时间线
- 15 — 交付敏感值二次查看与自审计闭环
- 16 — 交付审计导出与字段授权快照
- 17 — 交付审计保留、清理和运行监控
- 18 — 冻结审计中心跨仓前端契约与验收包
- 20 — 接入公共系统配置正式审计 Adapter
- 21 — 接入 Outbox 人工恢复正式审计 Adapter
- `.scratch/tech-public-foundation/issues/12-foundation-release-gate-and-integration-contract.md` — 12 — 建立公共基础发布门禁和下游接入契约
**Status:** ready-for-agent
**架构通道:** 主通道为 Infrastructure辅助通道为 Application/Query 验收。
**完整业务边界:** 本票收口全局审计一次性停机切换、迁移验证、旧写收缩、对账、性能、安全、监控和发布回滚边界。明确不允许长期双写或局部放量,不删除旧历史,不在新事实产生后通过删表回滚。
- [ ] 停机顺序明确覆盖暂停流量与 Worker、前置检查、增量迁移、权限初始化、新 Writer 装配、旧写护栏、历史对账、Worker 恢复和开放流量。
- [ ] 自动切换清单证明生产产物不再调用旧账号/资产审计 Writer、不再直接 Create 旧三表、启动装配不再注入旧 Writer旧表意外新增会立即告警或失败。
- [ ] 《审计覆盖基线》的全部入口均已分类且无空白项;所有 Audit Event 动作已注册,所有 N/A 均有评审理由,系统配置更新和 Outbox 人工恢复已装配正式 Audit Writer。
- [ ] 门禁覆盖关键业务与审计同事务、审计失败回滚、失败短事务、Integration 结果未知、历史新旧交界、Access Log 敏感矩阵和权限隔离。
- [ ] Query 性能验证常用过滤使用索引、无 JSONB 全表模糊扫描、无资源/操作者 N+1并满足项目 P95/P99 目标。
- [ ] 任一迁移、旧写清单、样本对账、事务、安全、权限、性能、监控或跨仓验收失败均在开放流量前整体终止发布,不能让局部模块继续写旧表。
- [ ] 发布与回滚说明明确:未产生新事实时可回退兼容应用;已产生 Audit/Integration/Outbox 事实后保留全部记录、停止异常生产者并前向修复,禁止恢复旧 Writer 或删除事实。
- [ ] 中文功能总结覆盖关键流程、前后端契约、异常闭环、发布回滚、监控恢复和待决策项README 增加索引;完整停机演练通过后方可放量。

View File

@@ -1,20 +0,0 @@
# 20 — 接入公共系统配置正式审计 Adapter
**What to build:** 在系统配置更新的 Application 组合根注入正式 Audit Writer Adapter使关键配置变更进入统一 Audit Event并按公共基础已经确认的事务边界失败关闭。由真实全局审计替换公共基础的未装配占位不创建临时审计表或旁路 goroutine。
**Blocked by:**
- 01 — 交付不可变 Audit Event 写入闭环
- `.scratch/tech-public-foundation/issues/08-controlled-system-config-update.md` — 08 — 交付系统配置更新、权限和审计闭环
**Status:** ready-for-agent
**架构通道:** 主通道为 Application + Port/Adapter辅助通道为 Infrastructure。
**完整业务边界:** 本票仅收口公共系统配置更新既有用例的正式审计装配、事务一致性、脱敏和测试。明确不新增配置 Key、不建设配置前端页面、不迁移其他业务审计。
- [ ] 注册系统配置更新的稳定动作编码、中文名称、风险等级及允许资源类型,并写入全系统审计覆盖基线。
- [ ] 系统配置更新的业务事实与 Audit Event 使用同一 GORM 事务;审计失败时配置更新回滚,敏感配置只记录“是否配置”和安全摘要,不记录原值。
- [ ] 组合根显式注入正式 Audit Writer Adapter未装配时失败关闭禁止回退到空实现、旧审计表或裸 goroutine。
- [ ] PostgreSQL 集成测试覆盖成功同事务、审计失败整体回滚、敏感值不落库和未装配失败关闭。
- [ ] 发布检查能证明生产组合根已装配正式 Adapter并由 19 号一次性切换门禁纳入停机演练。

View File

@@ -1,20 +0,0 @@
# 21 — 接入 Outbox 人工恢复正式审计 Adapter
**What to build:** 在 Outbox 人工恢复的 Application 组合根注入正式 Audit Writer Adapter使每次受控恢复完整记录操作者、原因、批次和状态变化并与恢复事实同事务失败关闭。由真实全局审计替换公共基础的未装配占位不创建临时审计表或旁路 goroutine。
**Blocked by:**
- 01 — 交付不可变 Audit Event 写入闭环
- `.scratch/tech-public-foundation/issues/04-outbox-observability-and-recovery.md` — 04 — 提供 Outbox 监控和受控恢复能力
**Status:** ready-for-agent
**架构通道:** 主通道为 Application + Port/Adapter辅助通道为 Infrastructure。
**完整业务边界:** 本票仅收口 Outbox 人工恢复既有用例的正式审计装配、事务一致性和测试。明确不改变恢复资格与租约规则、不建设 Outbox 前端页面、不迁移其他业务审计。
- [ ] 注册 Outbox 人工恢复的稳定动作编码、中文名称、风险等级及允许资源类型,并写入全系统审计覆盖基线。
- [ ] Outbox 状态变更与 Audit Event 使用同一 GORM 事务;记录操作者、中文原因、恢复批次、事件标识及恢复前后状态,审计失败时恢复回滚。
- [ ] 组合根显式注入正式 Audit Writer Adapter未装配时失败关闭禁止回退到空实现、旧审计表或裸 goroutine。
- [ ] PostgreSQL 集成测试覆盖成功同事务、审计失败整体回滚、重复恢复裁决、有效租约不可恢复和未装配失败关闭。
- [ ] 发布检查能证明生产组合根已装配正式 Adapter并由 19 号一次性切换门禁纳入停机演练。

View File

@@ -1,268 +0,0 @@
# 全系统审计覆盖基线
状态2026-08-06 当前源码最终重扫及业务语义、研发边界、安全字段三视角复核已完成;后续入口变更由静态门禁持续校验
## 可复核制品
- 显式逐入口清单:[`审计覆盖清单.json`](审计覆盖清单.json),当前共 692 项;七月旧 490 项只用于遗漏比对,不再作为现行契约。
- 扫描范围331 个 HTTP RouteSpec、39 个 Asynq Worker 注册语句35 个唯一 TaskType、12 个 Asynq 定时任务、33 个 Application、5 个 Domain、180 个旧 Service 公共业务入口、78 个 Integration Log 调用点、14 个 Outbox Consumer 注册点和 0 个旧 Writer 调用点。
- 生成入口:`go run ./cmd/audit-coverage`
- 发布门禁:重新执行 `go run ./cmd/audit-coverage`并通过清单差异、gopls、构建和数据库数据核对确认入口与决策同步。
- 每项均固定代码入口、业务所有者、中文摘要以及待评审的 Audit Event / Domain Ledger / Integration Log / Outbox 分类候选,并预留动作、风险、资源、操作者来源、事务边界、失败策略、前后数据、敏感策略和确认核对接缝。
- 当前 `Audit Event=N/A` 候选均填写逐入口理由;评审前不能据此宣称全系统分类已经确认。
生成器只负责产生待评审候选,不能自行代表评审通过。更新清单时必须核对业务语义,不能仅运行生成命令后直接提交。本轮复核已按下述证据完成,后续新增入口仍需重新执行同样流程。
## 2026-08-06 当前入口最终重扫结论
### 现行矩阵与旧清单差异
- 当前逐入口矩阵固定 `code_entry/kind/owner/action/actor/resource/transaction/visibility`,并分别登记 Audit Event、Domain Ledger、Integration Log、Outbox 或 N/A 理由692 项不存在空白决策字段,所有 Audit Event N/A 项均有理由。
- RouteSpec 从旧 270 项增至当前 331 项Worker 从 24 项增至 39 个注册语句35 个唯一 TaskTypeAsynq 定时任务从 4 项增至 12 项。当前另显式登记 78 个 Integration Log 调用点、14 个 Outbox Consumer 注册点和 0 个旧 Writer 调用点,避免用模块级泛化描述替代真实入口。
- 扫描器排除无 `context.Context` 的依赖注入 `SetXxx`、构造器、注册/装配函数和纯分发壳;普通 GET、购买检查和资产验证均按只读 N/A 登记。`SetSpeedTier` 因包含真实业务上下文和 Gateway 副作用保留为业务入口。
- Callback 使用 `external_system/callback` actorWorker 与消费者使用 `system_task/asynq`Scheduler 只投递任务时为 N/A真实业务变化归对应 Worker/Application。
### 敏感读取单列
| 入口 | 资源与安全决定 | 四类事实 |
|---|---|---|
| 企微应用配置 `GET /applications` | 返回 Secret、CallbackToken、EncodingAESKey返回前必须 fail-closed Audit凭据不得写入 Audit/Integration | Audit=必须Domain Ledger=只读配置Integration/Outbox=N/A |
| 资产实时状态 `GET /:identifier/realtime-status` | 设备响应含 WiFi 明文密码且实时访问 Gateway | Audit=必须Domain Ledger=只读Integration=每次尝试必须Outbox=N/A |
| IoT 卡实名链接 `GET /:iccid/realname-link` 与 C 端 `/realname/link` | 返回短期实名业务凭证 | Audit=必须Domain Ledger=只读卡事实;实际外部尝试写 IntegrationOutbox=N/A |
| 导出任务详情 `GET /export-tasks/:id` | 完成态返回预签名 `download_url` | Audit=必须导出任务是运行事实Integration=N/AOutbox=N/A |
| 批量下载/上传预签名 URL | 对象 Key 和 URL 受资源权限约束,签名 URL 不入审计正文 | Audit=必须Domain Ledger 按目标业务资源对象存储只写基础设施日志Outbox=N/A |
操作密码是否设置、实名状态、普通账号/资产/订单列表与统计均为普通受权读取Audit Event=N/AJSSDK 配置只返回客户端初始化签名,真实 token 回源由 Integration Log 记录,不把短期客户端配置误判为系统凭据读取。
### Integration Log 与旧 Writer 复核
- Integration Log 唯一 Repository 写入口为 `Start/Complete/RecordInbound/ClaimExpiredInboundPending`,当前已覆盖运营商回调、支付 H5 下单/查单/回调、卡观测、卡限速及企微 token/通讯录/模板/附件/提交/详情/回调;支付宝 WAP URL 本地签名不伪造外部尝试。
- 设备 Gateway、IoT 卡 Gateway、统一资产实时状态、支付、企微与运营商回调均已按真实外部尝试接入 Integration Log扫描器覆盖 `Start/Complete/RecordInbound/ClaimExpiredInboundPending`,不能用 Audit Event 或旧 Asset Operation Log 代替。
- 旧账号和旧资产 Writer、直接业务调用及裸/双重 goroutine 均已归零;旧账号表与旧资产表原样保留,旧资产仅保留独立历史只读入口。
### 已落地代表切片
- 受控系统配置更新使用 `system_config.updated`:成功与 `tb_system_config` 同事务,已注册只读/非法值拒绝及事务失败在业务未落地后同步写独立短事务;未注册 Key、空 Key 或无 actor 不生成无资源 Audit Event。
- Outbox 人工重放与过期租约释放分别使用 `outbox.replayed``outbox.expired_lease_released`:成功事件关联批次内全部 Outbox 资源并保存状态/租约前后值;重复恢复、有效租约等完整定位资源后的拒绝写 `denied`,业务事务或成功审计失败写 `failed`,均保持 Outbox 原状态。
- 失败/拒绝审计二次写入失败保留原业务错误,使用进程内原子计数器累计,并输出含 `severity=critical`、稳定 action/resource/request/correlation/error code 的安全日志;全链路无裸 goroutine。
### 三视角复核记录
- 业务语义:逐 RouteSpec、Application/Service、Worker/Callback/Consumer 追踪真实副作用,确认通知已读属于低风险写,购买检查/资产验证属于 N/A多资源、资金、批量和系统动作未按名称一刀切。
- 研发边界:核对 GORM 事务、Domain Ledger、Integration Repository、Outbox consumer/relay、旧 Writer 调用链Setter、注册器、纯查询和分发壳已剔除。
- 安全字段单列企微明文凭据、WiFi 密码、实名链接、预签名 URL/导出下载;平台内部、代理/企业安全投影和 `internal_only` 可见性已逐项填写,越权与不存在保持同错。
## 分类边界
| 入口类型 | Audit Event | Domain Ledger | Integration Log | Outbox |
|---|---|---|---|---|
| 状态变更、资金、权限、关键配置 | 必须;关键成功与业务事实同事务 | 既有业务表仍是权威 | 存在外部调用时必须 | 存在提交后可靠副作用时必须 |
| 失败、拒绝 | 业务回滚后独立短事务 | 不伪造领域事实 | 外部尝试仍记录真实结果 | 不为已回滚事实制造事件 |
| 普通读取 | N/A逐项记录理由 | 只读投影 | N/A | N/A |
| 敏感读取、下载和导出 | 返回敏感结果前必须,自审计失败则不返回 | 业务数据仍是权威 | N/A | 异步导出按任务契约决定 |
| 外部回调、轮询和 Gateway 调用 | 状态变化、人工触发、连续失败或高风险异常时必须 | 业务状态仍在领域表 | 每次实际或未发送尝试都必须 | 需要可靠后续处理时必须 |
| Domain 方法 | 不直接依赖审计基础设施,由 Application 写入 | 维护业务不变量 | 由 Application/Adapter 负责 | 只记录领域事件,由 Application 持久化 |
## 七月测试环境冻结期增量登记
`complete-july-iteration-test-release` 已明确把 Audit Event Writer 与发布门禁延期到任务 6.5。以下登记仅说明测试环境阶段的临时分类不代表生产评审通过也不得删除通知事实、Access Log 或公共 Outbox
| 入口 | Audit Event | Domain Ledger | Integration Log | Outbox |
|---|---|---|---|---|
| 明确后台账号通知事件消费与幂等写入 | N/A测试环境冻结生产前由 6.5 重新评审通知失败与系统告警治理) | `tb_notification` 是通知投递与接收人已读状态的权威事实 | N/A无外部系统调用 | 消费公共 Outbox 的稳定事件,不复制 Outbox |
| 当前后台账号单条通知已读 | N/A低风险个人阅读状态普通已读操作只进入 Access Log | `tb_notification.is_read/read_at` 是权威状态 | N/A | N/A |
| 当前后台账号未读数与基础列表 | N/A普通读取不返回其他接收人数据或敏感业务正文 | 只读 `tb_notification` 投影 | N/A | N/A |
| 代理主钱包订单统一扣款 | 使用 `agent_wallet.order_debit`,关联订单、主钱包和唯一成功流水,保存余额前后值;成功与订单、钱包、流水及 Outbox 同事务,审计失败回滚,已定位订单后的失败/拒绝在业务回滚后写独立短事务 | `tb_order``tb_agent_wallet``tb_agent_wallet_transaction``tb_payment` 与套餐使用记录在同一事务形成权威事实;现有行锁、乐观锁和唯一业务引用保持不变 | N/A不调用外部系统 | 同事务写入 `wallet.agent_main.debited`为余额预警等后续消费者提供稳定事实Audit Event 不替代 Outbox |
| 代理主钱包订单资金预占、释放与完成扣除 | 使用 `agent_wallet.order_reserve/order_release/order_complete`,关联订单、主钱包、预占事实及完成时的唯一扣款流水,保存余额和冻结余额前后值;成功与原资金事务同写,重复终态不伪造事件 | `tb_agent_wallet_reservation` 是预占金额、付款钱包与唯一终态的权威事实;钱包与完成扣除流水同事务更新。当前生产仅取消订单调用 releasefreeze/complete Application 接缝暂无生产调用者,已接好审计但不借本任务新增业务调用 | N/A不调用外部系统 | 同事务写入 `wallet.agent_main.reservation.changed`;完成扣除同时写入 `wallet.agent_main.debited`消费者按权威事实幂等确认Audit Event 不替代 Outbox |
| 代理主钱包充值与人工调整正向入账 | 充值沿用 `agent_recharge.credit`,以一条事件关联充值单、提交人、店铺、主钱包和唯一流水,避免为同一入账重复造事件;人工调整使用 `agent_wallet.adjust_balance`,要求保留人工原因并关联主钱包、唯一调整流水及余额前后值。成功与原资金事务同写,重复业务引用不伪造成功 | 充值/人工调整业务事实、`tb_agent_wallet` 与唯一成功流水在同一事务形成权威事实;当前没有人工调整生产入口,统一 Posting 接缝已覆盖但不借审计新增接口 | N/A本接缝不调用支付或审批外部系统 | 同事务写入 `wallet.agent_main.credited`,消费者按成功流水复核;支付/审批 Integration Log 由代理充值外部流程负责Audit Event 不替代 Outbox |
| 代理主钱包实际信用额度更新 | 使用 `agent_wallet.change_credit`,关联主钱包及所属店铺,保存 balance/frozen_balance 不变事实、credit_enabled/credit_limit/version 前后值;成功与信用字段版本条件更新同事务,已定位钱包后的资金占用拒绝、版本冲突或审计回滚失败使用独立短事务 | `tb_agent_wallet` 是实际信用开关、额度、余额、冻结余额和版本的权威事实;保持现有可用额度及资金占用校验,不产生钱包流水 | N/A本地信用配置不调用外部系统 | N/A信用额度更新不产生可靠异步副作用 |
| 代理在线充值支付链接创建 | 延期(测试环境冻结;创建人、店铺、金额和支付方式由充值单与支付单留痕,生产前按 6.5 复核 Audit Event | `tb_agent_recharge_record``tb_payment` 同事务保存待支付事实和收款身份快照 | 微信 v3 H5/v2 MWEB 下单每次真实外呼写 Integration Log支付宝 WAP URL 仅本地签名N/A后续查单与回调仍逐次记录 | N/A创建阶段不产生可靠异步副作用支付确认后才同事务写入钱包入账 Outbox |
| 代理订单主钱包退款回充 | `refund.approve` 与退款单、订单、原扣款钱包、原扣款流水和唯一退款流水同事务;重复退款流水不重复写成功事件 | 原成功扣款流水定位付款钱包并限定金额;退款审批、`tb_agent_wallet` 与唯一成功退款流水同事务形成权威事实 | N/A本资金接缝不调用渠道或审批外部系统原路渠道退款尚未实现 | 同事务写入 `wallet.agent_main.refunded`,消费者复核退款流水、原扣款事实、金额上限和资产快照 |
| 代理商资金概况信用投影 | N/A普通受权读取不返回其他数据范围的资金事实不执行资金或配置变更 | 只读投影 `tb_shop`、主/佣金钱包、提现汇总和主账号;派生金额不另建事实表 | N/A无外部系统调用 | N/A纯 Query 不产生可靠副作用) |
| 受控系统配置更新 | N/A用户已明确取消全局 Audit Event仅超级管理员可更新代码注册 Key未知 Key、非法类型和值域均拒绝 | `tb_system_config` 是配置值、类型、模块及更新人的 PostgreSQL 权威事实,更新后失效 Redis 缓存 | N/A配置更新不调用外部系统不得写 Integration Log 冒充配置审计) | N/A配置更新不产生可靠异步副作用 |
| 电信实名结果回调 | 实名状态首次实际变化时写 `iot_card.realname_callback_sync`,使用 `external_system/callback`,关联 IoT 卡和入站 Integration LogAudit Event 与卡状态、首次实名时间及实名变化 Outbox 同事务,审计失败回滚。已解析卡后的业务失败写独立短事务;重复成功不伪造事件 | `tb_iot_card` 是实名状态、首次实名时间和逆转窗口的权威事实 | 每次入站先写 `tb_integration_log`,仅保存正文摘要;覆盖 `invalid_payload/ignored/not_found/conflict/success/failed` 终态;未改变实名状态时只保留 Integration Log | 实名事实首次变化时由公共 `ApplyCardObservation` 同事务写入实名状态变化 Outbox重复成功不重复写事件 |
| 移动实名成功回调 | 实名状态首次实际变化时写 `iot_card.realname_callback_sync`,使用 `external_system/callback`,关联 IoT 卡和入站 Integration LogAudit Event 与卡状态、首次实名时间及实名变化 Outbox 同事务,审计失败回滚。已解析卡后的业务失败写独立短事务;重复成功不伪造事件 | `tb_iot_card` 是实名状态、首次实名时间和逆转窗口的权威事实 | 每次入站先写 `tb_integration_log`,仅保存正文摘要;覆盖 `invalid_payload/not_found/conflict/success/failed` 终态,并通过 pending 租约恢复中断处理;未改变实名状态时只保留 Integration Log | 仅合法成功报文进入公共 `ApplyCardObservation`;实名事实首次变化时同事务写入 Outbox重复成功不重复写事件 |
| 联通实名成功回调 | 实名状态首次实际变化时写 `iot_card.realname_callback_sync`,使用 `external_system/callback`,关联 IoT 卡和入站 Integration LogAudit Event 与卡状态、首次实名时间及实名变化 Outbox 同事务,审计失败回滚。已解析卡后的业务失败写独立短事务;重复成功不伪造事件 | `tb_iot_card` 是实名状态、首次实名时间和逆转窗口的权威事实;上游 `dateChanged` 只用于幂等和留痕 | 每次入站先写 `tb_integration_log` 正文摘要;覆盖 `invalid_payload/not_found/conflict/success/failed`,关闭时记录 `ignored`;未改变实名状态时只保留 Integration Log | 仅合法成功报文进入公共 `ApplyCardObservation`;实名事实首次变化时同事务写入 Outbox重复成功不重复写事件 |
| 联通解除实名回调 | N/A只识别并留痕外部解除通知不把单次回调作为本地实名逆转事实 | `tb_iot_card` 保持原实名状态、首次实名时间、检查时间及逆转计数,回调不写领域事实 | 每次入站先写 `tb_integration_log` 正文摘要;覆盖 `invalid_payload/not_found/conflict/ignored/failed` 终态并支持 pending 租约恢复 | N/A不调用公共实名观测不产生状态变化、停机或套餐事件 |
## 七月确认范围增量登记
| 入口 | Audit Event | Domain Ledger | Integration Log | Outbox |
|---|---|---|---|---|
| 换货迁移套餐在原订单退款后失效 | N/A退款终态的自动后处理不新增人工决定人工申请与审批审计沿用退款入口 | 原订单、换货新旧资产关系和 `tb_package_usage` 是套餐权益来源及失效状态的权威事实;仅失效该订单迁移后的对应权益 | N/A本地数据库后处理不调用企微、支付或 Gateway | 企微退款沿用 `approval.terminal_decision.recorded` 驱动;存量旧退款沿用原同步链路,本修复不新增 Outbox |
| 订单渠道、资产标识、退款/充值/换货提交人和卡/设备实名筛选 | N/A均为字段来源修正或受权只读投影不改变订单、资产、实名或审批事实 | 只读既有订单 `purchase_role`、卡 ICCID、设备 VirtualNo/IMEI、创建人账号及有效卡绑定实名事实不另建领域账本 | N/A查询使用本地批量账号查询和 EXISTS不实时调用外部系统 | N/A纯查询和创建时既有字段赋值不产生新增可靠副作用 |
| 换货创建前未终结退款拦截 | 已识别旧卡或旧设备后分别使用 `exchange.card.create``exchange.device.create` 记录 `denied`,关联稳定换货单 Key、旧资产和店铺 | `tb_refund_request` 的未终结状态是拦截依据;拒绝后不创建换货单、不修改资产 | N/A本地前置校验不调用企微或其他外部系统 | N/A校验拒绝不产生业务事实或可靠副作用 |
| 店铺 C 端新登录限制配置与登录拦截 | 店铺更新入口记录操作者 `updater`、字段前后值进入 Access Log本 Change 不新建店铺专用 Audit Writer统一店铺配置 Audit Event 接缝登记为后续治理项 | `tb_shop.client_login_disabled` 是是否允许新登录的权威事实;已有 Token 不修改,拦截时不创建新 Token | N/A配置更新与资产登录判断均为本地数据库操作 | N/A同步配置与登录前拦截不产生必须可靠投递的提交后副作用 |
| 卡/设备实名策略单个及批量更新 | IoT 卡使用 `iot_card.realname_policy_update` / `iot_card.realname_policy_batch_update`,设备使用 `device.realname_policy_update` / `device.realname_policy_batch_update`;均记录真实后台操作者、目标资产、实际绑定卡/设备与卡槽引用、策略前后值及 success/failed/denied批量根子事件与实际策略变化同事务 | `tb_iot_card.realname_policy``tb_device.realname_policy` 是策略权威事实C 端仅实时计算 `effective_realname_policy` | N/A策略更新和读取均不调用运营商或其他外部系统 | N/A策略同步更新不产生可靠异步副作用 |
| 下架套餐当前使用者续费与普通列表过滤 | N/A普通受权查询与既有订单创建规则订单创建继续沿用原订单/资金审计接缝) | 当前套餐使用记录决定续费资格,新订单、订单明细、套餐当前配置和支付记录是新购买权威事实;不修改历史订单 | 第三方支付仍沿用既有支付 Integration Log本资格判断不新增外部调用 | 新订单支付、钱包扣款、自动购包及佣金继续沿用既有任务/Outbox本切片不新增事件类型 |
| 卡/设备 C 端支付方式配置更新 | 复用 `systemconfig.UpdateService` 的事务内 `AuditWriter`,记录操作者、请求标识及配置前后值;审计 Writer 已装配时写入失败会回滚配置更新 | `tb_system_config` 是卡、设备允许支付方式集合及更新人的 PostgreSQL 权威事实Redis 仅为可失效缓存 | N/A配置更新不调用外部系统 | N/A提交后仅失效可重建缓存不产生必须可靠投递的业务副作用 |
| C 端读取支付方式与后端订单/充值校验 | N/A普通受权读取和业务规则校验不产生独立敏感事实拒绝原因进入 Access Log | 只读 `tb_system_config`,订单创建后由 `tb_order.payment_method` 固化所选方式,充值与支付事实沿用既有订单、充值单和支付记录 | 第三方支付请求继续沿用既有支付集成日志接缝,本配置策略本身不新增外部调用 | 强充支付成功后的自动购包继续沿用既有 Asynq/业务幂等链路,本配置读取不新增 Outbox |
| 主钱包首次跌破 100 元通知店铺业务员 | N/A由已审计资金事实派生的内部提醒不新增人工操作或敏感读取 | `tb_agent_wallet_transaction``wallet.agent_main.debited` 是余额前后值的权威事实,`tb_notification` 保存最终通知与已读状态 | N/A不调用外部系统 | 扣款事实消费者仅在 `balance_before >= 10000 && balance_after < 10000` 时同事务幂等写入明确后台账号通知 Outbox无有效业务员时正常结束 |
| 创建物流换货单并提醒关联个人客户 | 卡/设备换货分别使用 `exchange.card.create``exchange.device.create` 记录真实后台操作者、换货单、旧资产和店铺,成功事实与换货单及通知 Outbox 同一 GORM 事务 | `tb_exchange_order` 是物流换货申请及状态的权威事实,`tb_notification` 是接收人通知与已读状态的权威事实 | N/A不调用外部系统 | 换货单与每个启用关联客户的 `notification.personal_customer.direct.requested` 在同一 GORM 事务写入;事件 ID 使用换货单和客户 ID 稳定防重,消费端按事件与接收人唯一键幂等 |
| 套餐临期列表、数量与每日/手动 15/7/3 天节点提醒 | N/A列表和数量是普通受权读取手动入口仅允许超级管理员提交同一幂等扫描任务操作者进入 Access Log 和任务日志,不直接修改业务事实) | `tb_package_usage` 的计时条款快照和到期队列是预计最终到期的权威事实,`tb_notification` 保存店铺账号、平台业务员和个人账号通知及已读状态 | N/A不调用企业微信、短信、邮件或其他外部系统 | 每日或手动任务按资产、到期日和节点生成稳定事件 ID同一 GORM 事务内向店铺动态接收人写入 `notification.admin.dynamic.requested`,并向绑定个人账号写入 `notification.personal_customer.direct.requested`;列表和数量纯 Query 不产生 Outbox |
| 主套餐过期接续与孤儿恢复 | N/A系统自动推进套餐生命周期不包含人工敏感操作 | `tb_package_usage` 是套餐待生效、生效、用完和过期状态的权威事实 | N/A仅使用本地 PostgreSQL 与 Redis不新增外部请求 | 成功激活继续在同一事务复用 `card.observation.series.requested`,稳定事件 ID 基于套餐使用记录 ID不新增套餐激活事件类型或消费者 |
| 企业微信应用连接配置保存与明文读取 | 配置保存和默认发起人分别使用 `wecom.application.save``wecom.application.save_default_creator`,只记录应用标识、状态和真实 `credentials_configured` 布尔事实;明文列表读取仅允许超级管理员,返回前以独立短事务同步写 `wecom.application.credentials_read`审计缺失或失败均不返回结果Audit Writer 不接收 Secret、回调 Token 或 EncodingAESKey | `tb_wecom_application` 是 corp_id、agent_id、应用状态及明文 Secret、回调 Token、EncodingAESKey 的权威事实;管理响应按用户确认向超级管理员返回明文 | 保存和读取本身不调用企微;连接测试或 token 缓存未命中时,每次真实回源均写 `tb_integration_log`,请求和响应摘要不含 Secret、回调凭据或 access_token | N/A连接配置提交后仅同步失效可重建 token 缓存,不产生必须可靠投递的业务副作用) |
| 支付连接配置 CRUD 与启停 | 使用 `payment_config.create/update/delete/activate/deactivate`,保存配置 ID、名称、渠道、启用状态、非敏感商户/应用标识和各渠道 `credentials_configured` 安全事实;不保存 Secret、Token、AESKey、支付密钥、私钥、公钥正文或证书正文。创建字段校验、删除生效配置或在途业务等已定位资源后的拒绝写独立短事务激活其他配置时为被自动停用的原配置另写同事务停用事件 | `tb_wechat_config` 是配置及明文渠道凭据的权威事实CRUD/启停与 Audit Event 同一 GORM 事务,审计失败回滚配置事实,提交后 Redis 缓存仅 best-effort 失效 | N/A配置 CRUD/启停不调用渠道;支付、查单和回调的真实外部尝试仍由 7.4 Integration Log 负责) | N/A配置提交不产生可靠异步副作用 |
| 运营商配置 CRUD 与启停 | 使用 `carrier.create/update/delete/update_status`,保存配置 ID、编码、名称、类型、状态、流量重置日和实名链接业务配置重复编码、非法模板配置等已定位资源后的拒绝进入独立短事务 | `tb_carrier` 是运营商及实名链接配置权威事实;成功审计与 CRUD/状态变更同一 GORM 事务 | N/A本切片只改本地运营商配置不调用 Gateway 或运营商) | N/A同步配置不产生可靠异步副作用 |
| 运营商回调开关与卡/设备支付方式等受控连接策略 | 继续复用 `system_config.updated`,记录注册 Key、模块、前后值、操作者和请求链路只读、非法值和事务失败沿用已落地的拒绝/失败短事务策略 | `tb_system_config` 是回调启停和支付方式策略权威事实,代码 Registry 默认值与 Redis 缓存不替代 PostgreSQL | N/A配置本身不调用运营商或支付渠道真实回调/支付尝试由各自 Integration Log 记录) | N/A提交后仅失效可重建缓存 |
| 企业微信可见成员同步与账号显式绑定 | 成员同步使用 `wecom.application.sync_members`,记录应用身份、状态、同步数量和时间,成员快照替换与 Audit Event 同一事务;账号绑定继续使用 `account.bind_wecom`,记录操作者、目标账号及绑定前后 `(corp_id, userid, name)`,不记录手机号或邮箱 | `tb_wecom_member` 是最近同步的应用可见成员选择快照,`tb_account.wecom_*` 是管理员确认后的账号绑定事实;不建立部门组织模型 | 每次真实调用应用可见成员接口均写 `tb_integration_log`,仅记录应用、根部门、成员数量、状态码和耗时,不保存 access_token 或成员列表正文 | N/A同步和绑定均为同步事务不产生必须可靠投递的提交后副作用 |
| 企业微信审批业务场景与模板控件映射 | 配置保存使用 `wecom.approval_scene.save`,记录场景 ID、业务类型、应用 ID、模板 ID/名称、状态、指纹和最近校验时间;配置与审计同事务,不保存凭据、审批节点或审批人规则到审计数据 | `tb_wecom_approval_scene` 是两个稳定业务类型的当前模板、控件映射、模板最小快照和启用状态权威事实 | 保存前每次真实调用模板详情接口均写 `tb_integration_log`,记录应用、模板 ID、状态码、控件数量和耗时不保存 access_token 或完整外部响应 | N/A配置保存为同步事务不产生必须可靠投递的提交后副作用 |
| 企业微信默认发起人与审批提交 | 默认发起人配置继续复用事务内 `systemconfig.AuditWriter`;业务事务创建通用审批时写 `approval.request`,关联真实提交账号、退款或线下充值业务单及 `approval.submission.requested` Outbox。企微提交 Worker 以 `system_task/worker``approval.sync_submission` 的 success/failed/unknown不以默认成员伪造操作者 | `tb_wecom_application.default_creator_*` 是当前默认发起配置,`tb_approval_instance``tb_wecom_approval_context` 是审批和提交状态权威事实Audit Event 仅保存状态变化及稳定引用 | 每次附件上传和 applyevent 均写精确 Integration Log摘要不含 Secret、access_token、media_id、附件正文或完整企微响应提交审计引用对应 `integration_id`,但不替代或冻结其可变结果 | 业务事务写入 `approval.submission.requested`Worker 条件领取后只提交一次,明确失败和结果未知均终结自动重试,禁止盲目创建第二张审批单 |
| 企业微信审批加密回调与详情终态同步 | 首次权威终态写 `approval.sync_decision`,回调使用真实 `external_system/callback` actor关联审批实例、业务单、真实提交账号、入站回调/详情 Integration 及终态 Outbox不记录本地或企微审批人为操作者。重复终态未改变审批事实时不伪造成功事件 | `tb_integration_log` 保存回调和详情外部事实,`tb_wecom_approval_context.latest_detail_snapshot`、通用审批实例及决策投递表保存权威标准终态Audit Event 与审批状态、决策投递和终态 Outbox 同事务 | 入站回调先写 Integration Log pending详情任务完成后置 completed每次 `getapprovaldetail` 写独立出站 Integration Log。审计只引用稳定 `integration_id` 与身份字段,不保存 access_token、完整响应或尚可变化的 Integration result | 回调只入队结构化 `wecom:approval:sync` 任务;权威终态原子写 `approval.terminal_decision.recorded`,退款和线下充值消费者继续使用既有业务/资金审计,并传播终态 Outbox 的 correlation/parent |
| 企业微信审批主动恢复、未终态轮询与审批人读取投影 | 唯一确认结果未知提交时写 `approval.recover_submission`:回调恢复使用 `external_system/callback`,主动恢复使用 `scheduled_job/scheduler`;轮询取得首次权威终态写 `approval.sync_decision`。普通审批人读取投影仍为 N/A重复恢复或重复终态未改变事实时不写成功事件 | `tb_wecom_approval_context.submission_attempted_at/last_recovery_at/sp_no/latest_detail_snapshot` 与通用审批实例是恢复和展示的权威本地事实;只有唯一候选可从结果未知转为审批中 | 每次 `getapprovalinfo` 分页和 `getapprovaldetail` 均写独立出站 Integration Log恢复审计关联实际提交或查询 Integration只保存安全摘要不保存 Secret、access_token、media_id、附件正文或完整响应 | Scheduler 仅提交 `wecom:approval:recovery`;恢复和轮询只提交结构化 `wecom:approval:sync`,不写新的审批提交 Outbox、不调用 `applyevent`,标准终态继续使用既有终态 Outbox |
| 员工线下代充值申请与企微终态入账 | 申请保存以真实提交人及明文业务快照留痕;资金成功 Audit Event 延期至既有统一钱包治理任务,企微自动终态不伪造人工审批人 | `tb_agent_recharge_record``tb_approval_instance``tb_wecom_approval_context` 同事务保存申请事实approved 通过 `topup + recharge_record_id` 唯一成功钱包流水幂等入账,其他终态不修改钱包,通过后撤销不自动冲正;`tb_notification` 保存到账通知 | 申请创建本身不外呼后续附件上传、applyevent、详情与恢复沿用企微 Integration Log业务参数按用户确认保存明文日志仍不记录 Secret、access_token、media_id 或附件正文 | 创建事务写 `approval.submission.requested`;标准终态写 `approval.terminal_decision.recorded`approved 入账事务再写 `wallet.agent_main.credited` 和目标店铺的 `notification.admin.dynamic.requested`;在线充值复用同一入账接缝;新审批单禁止旧人工确认或驳回入口绕过 |
| 代理充值列表、详情与支付状态读取 | N/A普通受权读取请求进入 Access Log不改变充值、支付或钱包事实 | 只读 `tb_agent_recharge_record`、相关支付单和店铺名称;平台账号不限制,代理账号统一按当前上下文的自身及下级店铺 ID 过滤 | N/A不调用支付渠道或企微 | N/A纯 Query不产生 Outbox |
| 退款申请与企微终态处理 | 申请、人工/企微通过与拒绝、退回、重提使用 `refund.create/approve/reject/return/resubmit`;佣金实际回扣使用 `refund.invalidate_commission`,资产后处理完成使用 `refund.process_asset`。成功事实与各自 Domain Ledger 同事务,已定位退款后的失败/拒绝使用独立短事务;代理/企业仅看到“已提交/已通过/已拒绝/处理完成”等安全结论 | `tb_refund_request`、通用审批实例和企微上下文同事务保存approved 条件更新订单与退款单,代理主钱包按 refund ID、资产钱包按退款单号复核成功回款佣金按记录锁定并失效套餐按订单及换货迁移关系幂等失效`tb_notification` 保存退款完成通知。Audit Event 关联退款、审批、订单、资产、钱包、原扣款/退款流水、佣金、实际失效套餐权益和通知 Outbox但不替代这些权威事实 | 申请创建不外呼附件、applyevent、详情、回调和恢复沿用企微 Integration Log业务参数明文保存在业务/审批快照中但不复制到 Integration LogSecret、access_token、media_id 和附件正文仍禁止记录原路渠道退款未实现Integration Log 明确 N/A | 创建事务写 `approval.submission.requested`;终态写 `approval.terminal_decision.recorded`;退款事务幂等写目标店铺的 `notification.admin.dynamic.requested`;通知继续以 Outbox 为权威投递事实Audit Event 仅保存稳定引用;业务消费者只有在订单、钱包、佣金和资产后处理完成后才确认投递成功,失败释放租约重试 |
| 退款与线下代充值旧审批入口发布切换 | N/A部署环境开关控制旧入口是否可用不新增业务操作实际旧入口操作继续沿用各自既有审计口径 | `approval_instance_id IS NULL` 是存量旧 provider 的兼容边界,非空记录只接受企微标准终态;关闭开关不修改或删除任何业务事实 | N/A开关判断不调用外部系统也不得写 Integration Log 冒充发布审计) | N/A开关判断不产生可靠副作用企微 Worker 继续消费既有标准终态 Outbox |
| IoT 卡/设备导入与设备 CSV 批量操作 | 创建使用 `iot_card_import_task.create``device_import_task.create`,完成使用对应 `*.complete` 根事件;任务只保存 ID/单号、文件名、运营商或操作目标和操作者,不保存 StorageKey、签名 URL 或文件正文。每张实际新增卡/设备继续使用既有 `iot_card.create/device.create` 业务子事件并以完成根为 parent设备 CSV 分配/系列/回收继续复用既有批量根子审计。跳过项不伪造子事件,根事件 success/partial/failed 与实际子事件及失败统计一致 | `tb_iot_card_import_task``tb_device_import_task` 保存任务输入、进度和逐项结果;卡、设备、资产标识、卡槽绑定、钱包及分配/系列事实仍由原业务表权威保存Audit Event 不替代任务或资产事实 | 对象存储下载只读取任务表中的 StorageKey不写 Integration Log审计源头只使用安全文件名。设备批量操作本身不新增外部调用 | HTTP 创建继续提交结构化 `IotCardImportPayload/DeviceImportPayload`Worker 使用任务单号 correlation 和稳定完成根 parent重试通过稳定 EventID 与原业务幂等规则避免重复子事件 |
| 单列 CSV 资产套餐批量订购 | 使用 `asset_package_batch_order_task.create/complete` 记录任务、文件名、套餐目标、支付方式、操作者和实际根子统计;既有 `order.create` 作为每个真实订单子事件并继承任务 correlation/parent不另造同义订单审计。StorageKey、VoucherKey、签名 URL 和 CSV 正文不进入审计 | `tb_asset_package_batch_order_task` 保存输入参数和逐行结果,成功行以 `tb_order`、订单明细、套餐使用、支付记录及代理钱包成功流水为权威业务事实 | 对象存储上传和下载沿用现有存储日志,不把文件正文写入 Integration Log本切片不新增外部支付或 Gateway 调用 | 创建接口提交结构化 `asset:package:batch_order` Asynq 任务;逐行钱包订单继续沿用既有钱包扣款 Outbox 和佣金任务,重复任务由状态条件与订单幂等规则阻断 |
| 订单套餐 CSV 批量失效 | 使用 `order_package_invalidate_task.create/complete` 记录任务根,使用 `order_package_invalidate_task.item` 为每个实际变化或已识别失败订单写子事件;订单为主要资源,实际失效套餐权益逐条关联并保存状态 `before→4`。无有效权益的幂等行不伪造变化子事件;任务 UI 统计与审计实际子事件统计分别保留 | `tb_order_package_invalidate_task` 保存文件任务状态和失败明细,`tb_package_usage.status` 是套餐权益终态权威事实;逐订单状态更新与子事件同一事务,任务终态与完成根同一事务 | 对象存储只用于读取 CSVStorageKey、VoucherKey、签名 URL 和文件正文不进入 Audit/Integration | 创建接口提交结构化 `InvalidateTaskPayload`Worker 原子 Claim审计失败时任务恢复待处理以便安全重试稳定子事件 ID 防止重复写入 |
| ICCID 批量生成待失效订单号 CSV | N/A脚本复用现有受权资产套餐查询属于运维只读投影请求进入 Access Log不改变套餐或订单事实 | N/A只读取 `tb_package_usage` 的状态和订单号快照,不写入领域账本;实际失效仍由既有批量失效任务负责) | N/A只调用本系统后台接口不调用 Gateway、支付或其他外部系统 | N/A纯查询和本地 CSV 生成,不产生 Outbox 或异步任务) |
| CSV 批量修改生效中套餐过期时间 | 每条修改复用既有 `asset_package_expires_at` 资产操作审计,记录操作者、资产、套餐使用记录及过期时间前后值和 success/failed 结果 | `tb_package_usage.expires_at` 是套餐过期时间权威事实;脚本只通过受权接口逐条修改,不直连数据库 | N/A仅调用本系统后台接口不调用 Gateway、支付或其他外部系统 | N/A同步修改不产生新增 Outbox后续套餐过期推进沿用既有轮询任务 |
| IoT 卡与套餐业务导出 | 创建/取消统一使用 `export_task.create/cancel`记录任务单号、scene、format、真实操作者和店铺范围取消状态或取消请求与 Audit Event 同事务。导出 Query、FileKey、签名下载 URL 和导出内容不进入审计;导出数据读取本身仍为 N/A | N/A导出只读取现有卡、套餐使用、套餐和分配事实不写入领域账本 | N/A不调用外部业务系统对象存储文件生成和下载沿用现有导出基础设施日志 | 沿用现有 `export:dispatch``export:shard``export:finalize` Asynq 链路,不新增业务 Outbox审计中心自身不注册导出路由 |
| 钱包流水与代理充值业务导出 | 创建/取消统一使用 `export_task.create/cancel`,只保存任务身份、格式、操作者和受控店铺范围,不复制 Query、业务凭证 Key、FileKey、签名 URL 或导出内容 | N/A只读取主钱包流水、充值记录和本地通用审批实例金额及余额使用既有权威事实不写入领域账本 | N/A不实时调用支付渠道或企业微信明文业务凭证 Key 只进入有权导出结果,不复制到 Audit/Integration且仍禁止记录 Secret、access_token、media_id 和附件正文 | 仅沿用现有 `export:dispatch``export:shard``export:finalize` Asynq 链路,不新增业务 Outbox取消重复请求不伪造新的状态变化事件 |
| 退款与换货业务导出 | 创建/取消统一使用 `export_task.create/cancel`;平台或代理 actor、scene/format 和当前权限范围进入任务资源Query、收货资料、业务凭证、FileKey、签名 URL 与结果正文不进入审计 | N/A只读取退款、订单、套餐使用、换货资产快照和本地审批事实金额及处理标记沿用既有权威事实不写入领域账本 | N/A不实时调用企业微信、支付或 Gateway明文业务凭证和收货资料只进入有权导出结果不复制到 Audit/Integration且仍禁止记录 Secret、access_token、media_id 和附件正文 | 仅沿用现有 `export:dispatch``export:shard``export:finalize` Asynq 链路,不新增业务 Outbox审计中心不提供用户导出 |
| 站内通知生成、已读与保留清理 | Outbox 消费实际生成通知使用 `notification.deliver`,只保存通知 ID、事件 ID、接收人、类别、类型、严重级别和受控资源引用不复制标题或正文后台账号与个人客户首次单条/全部已读使用 `notification.read/read_all`,重复已读不伪造事件;保留清理使用 `notification.cleanup/cleanup_item`,由 `system_task/worker` 记录批次和每条实际删除通知。通知创建、已读更新或物理删除与对应 Audit Event 共用 GORM 事务,审计失败回滚业务事实 | `tb_notification` 继续是通知内容、接收人、展示期限和已读状态的权威事实Audit Event 只解释生成、阅读和清理动作,不替代通知正文或接收状态 | N/A站内通知不调用短信、邮件、企微或其他外部系统受控 `ref_id/ref_key` 禁止 URL系统安全凭据和通知正文不进入审计 | 业务事务仍只写现有三类结构化通知请求 OutboxOutbox 投递事实与通知生成 Audit Event 分离,重复消费由事件+接收人唯一键幂等;清理继续复用 `notification:cleanup` Asynq 计划任务,不新增 Outbox |
| IoT 卡固定档位限速 | 统一动作 `iot_card.speed_tier_set` 记录认证上下文中的真实操作者、目标卡 ID/ICCID、请求档位编码与名称如 128Kbps/1Mbps/恢复不限速、Integration Log ID、Integration 是否终结及 success/failed/unknown 结果;设备无入口且不通过绑定卡间接限速 | N/A不在本地保存或修改卡当前限速状态Gateway 是外部执行方 | 每次实际 Gateway 调用前写 pending按 success/failed/unknown 终结;超时 unknown 保存按 ICCID 人工核对策略,摘要不含操作者或 Secret、access_token、完整响应正文 | N/A单次外部命令无后续可靠副作用结果未知禁止盲目重发不创建自动补偿 Outbox |
| IoT 卡人工实名状态纠偏 | `iot_card.realname_status_update` 记录真实后台操作者、目标卡、实名状态前后值及是否实际变化状态事实、Audit Event 和实名变化 Outbox 在同一 GORM 事务,失败写独立短事务 | `tb_iot_card.real_name_status`、首次实名时间及激活字段是内部实名事实 | N/A人工纠偏不直接调用 Gateway | 状态实际变化时复用 `card.realname.changed`,未变化不伪造变化事件 |
| IoT 卡后台/个人人工刷新 | 后台使用 `iot_card.manual_refresh`,个人客户使用 `iot_card.personal_refresh`;记录真实 actor、目标卡、实际状态变化及最终 success/partial/failed/unknown任一结果未知不写成成功 | 卡网络、实名、流量及 `last_sync_time` 是内部观测事实;各实际变化与统一 Audit Event 同事务 | 网络、实名、流量查询的每次真实 HTTP 尝试分别写 Integration Log失败/超时逐次终结,成功尝试在内部应用结果确定后记录 `state_changed` | 实名、网络、流量实际变化沿用各自 Card Observation Outbox人工刷新汇总不另造可靠事件 |
| IoT 卡人工/OpenAPI/自动/保护期停复机 | 分别使用 `iot_card.manual_stop``iot_card.manual_start``iot_card.openapi_start``iot_card.auto_stop``iot_card.auto_start``iot_card.auto_stop_reason_update`;记录真实人工/OpenAPI/system actor、目标卡、关联设备与卡槽、停复机原因、状态前后值、Integration ID 及 success/failed/denied/unknown保护期强制修正复用同一服务不再旁路审计 | `tb_iot_card.network_status/stopped_at/resumed_at/stop_reason/gateway_extend` 是内部状态权威事实 | 保持既有内外层重试次数和退避;每次真实 Gateway HTTP 分别写同一 `trigger_series` 下单调递增 attempt超时为 unknown成功尝试待状态事务结束后终结 | 状态、Audit Event 与 `card.observation.series.requested` 同事务;停复机完成后沿用轮询重排,不新增补偿 Outbox |
| 单笔资产分配/回收 | 当前无独立通用单笔写入口IoT 卡和设备同步分配/回收接口在请求仅含一个资产时,分别复用 `iot_card.allocate/recall``device.allocate/recall` 单资源子事件,记录真实后台或代理操作者、资产、分配记录、来源/目标店铺;设备同时关联实际连带变化的卡和卡槽 binding。每个已识别资源的拒绝/失败仍进入对应子事件,不另造 `asset.*` 重复动作 | 卡/设备归属与状态、实际连带卡归属及 `tb_asset_allocation_record` 是权威业务事实;单项事实、分配记录和 Audit Event 沿用 6.2/6.5 已有同一 GORM 事务 | N/A本地资产归属事务不调用 Gateway、支付、企微或其他外部系统 | N/A同步流转不产生新增可靠副作用提交后缓存失效和轮询通知保持既有顺序。批量请求根事件及 CSV 批量任务分别沿用 6.2/6.5 和 6.9,不在本切片重复实现 |
| 设备 CSV 批量分配、设置套餐系列或回收 | Worker 使用真实 `system_task/worker` 上下文,每个任务以稳定 `task_no` 作为 correlation 和批次键,仅对尚未达到目标关系的设备调用一次现有设备批量服务,复用 `device.allocate_batch`/`device.allocate``device.series_binding_batch`/`device.series_binding``device.recall_batch`/`device.recall` 根子事件;根事件统计与已识别设备子事件一致,实际绑定卡和卡槽随设备子事件进入各自资源时间线,不再另写 CSV 专用设备事实审计。任务查询的 `target_name` 仅批量投影当前店铺或套餐系列名称 | 设备归属、实际绑定卡归属、`tb_asset_allocation_record``series_id` 是权威业务事实;成功事实与 Audit Event 共用设备服务原 GORM 事务,审计失败回滚业务,不另建领域账本 | N/ACSV 解析、分配、系列绑定和回收均为本地数据库操作,不调用 Gateway、支付或企微对象存储沿用现有存储日志 | 复用 `device:import` Asynq 任务;完成/失败状态阻止终态任务重复执行,处理中断恢复时已达到目标关系的设备不再写业务事实或成功子事件,其余设备仍使用相同 `task_no` 保持审计幂等,不新增业务 Outbox |
| 设备停复机、Wi-Fi、切卡模式、重启和重置 | 使用 `device.stop``device.start``device.set_wifi``device.set_switch_mode``device.reboot``device.reset`,记录后台、个人或 OpenAPI 的真实 actor/source、设备、实际绑定卡与卡槽引用、命令参数、Integration ID 及 success/failed/denied/unknownWi-Fi 只记录 `credentials_configured`,不记录密码;当前卡切换由独立卡槽关系用例记录 | 停复机只修改实际处理卡的 `network_status/stopped_at/resumed_at/stop_reason`Wi-Fi、模式、重启和重置无同步本地状态变化只记录外部命令结论不伪造设备字段已生效`enabled` 当前未下发,登记 N/A | 保留 Gateway 既有重试与退避,每次真实 HTTP 尝试写同一 `trigger_series` 下的独立 attempt停复机按实际卡记录其他命令按设备记录超时为 unknown成功尝试在本地事务结果明确后终结 | 停复机的卡状态、Audit Event 与既有 `card.observation.series.requested` 同一事务,并保留保护期和轮询缓存失效;其他命令成功后沿用 best-effort 观测分发。Worker/Scheduler/Callback 不直接执行这些设备命令,自动停复机继续由 6.3 卡级审计覆盖 |
| 设备绑卡、解绑与当前卡切换 | 使用 `device.bind_card``device.unbind_card``device.switch_current_card`;记录后台账号、个人客户或 OpenAPI 的真实 actor/source设备、目标卡、旧/新当前卡及实际相关 binding 均为独立资源binding 快照及 before/after 固化 `slot_position/is_current`;设备导入和删除产生的隐式绑卡/解绑继续使用既有 `device.create/delete`,但同样关联每张卡和 binding已识别设备后的拒绝、失败和 unknown 使用独立短事务 | `tb_device_sim_binding.bind_status/slot_position/is_current` 是设备 1-4 卡槽及当前卡的权威内部事实;绑卡创建、解绑状态和切卡当前标识与 Audit Event 同一 GORM 事务,卡的 `device_virtual_no` 仍保持原提交后 best-effort 快照语义 | 绑卡、解绑 N/A纯本地事务切卡每次真实 Gateway HTTP 尝试写相同 `trigger_series` 下的独立 Integration Log attempt超时为 unknown目标卡必须是当前设备有效绑定卡Integration 只表达外呼结果,不提前声称本地状态已变化 | 切卡成功后保留既有 Card Observation best-effort 分发,用 Gateway 后续观测校准真实当前槽位;观测 Worker 的自动回写属于 8.7,本切片不重复审计;不新增 Outbox 类型,不迁移设备/卡其他状态机。后台绑卡/解绑只有平台入口,切卡三类入口汇聚共享 Service三组旧资产 operation log 已停止 |
| 订单创建、取消、钱包支付与过期关闭 | 使用 `order.create``order.cancel``order.wallet_pay``order.expire_close`;后台创建/代购记录真实账号C 端记录个人客户,代理 OpenAPI 记录 OpenAPI actor资产套餐批量订购逐笔记录 `system_task/worker`,过期关闭记录 `scheduled_job/scheduler`。事件关联订单、买家、卡或设备、套餐、实际钱包/流水和 Payment订单快照保存金额、支付方式/状态、购买角色及操作者;成功与原订单事务同写,已识别订单或资产后的拒绝/失败使用独立短事务。普通订单列表和详情仍为受权读取 N/A | `tb_order``tb_order_item``tb_payment``tb_package_usage``tb_agent_wallet`/`tb_asset_wallet` 及对应唯一流水继续是订单、套餐和资金权威事实Audit Event 不替代余额、支付或权益账本。钱包下单及待支付后的钱包支付均在原 GORM 事务内追加审计,审计失败回滚业务;重复命中且未发生状态变化时不伪造成功事件 | 本切片不直接调用支付渠道或 GatewayIntegration Log=N/A微信、支付宝、富友预下单、查单和回调属于 7.4,不能用订单事件替代外部尝试记录 | 代理钱包扣款继续在同一事务写既有钱包 Outbox佣金任务和套餐观测沿用原提交后链路Audit Event 不替代 Outbox。OpenAPI/CSV 批量根事件与 partial 统计属于 8.3,本切片只记录每笔实际订单,不提前伪造批次根事件 |
| 支付外部尝试与内部终态 | 使用 `payment.create``payment.confirm``payment.fail`;没有独立 Payment 的旧订单回调使用 `order.online_pay`。支付单为主要资源,订单或充值单为业务单资源,渠道交易号保存在支付快照;个人资产充值确认同时关联实际变化的钱包和唯一流水。支付创建、明确关闭及回调确认均与对应 Payment、订单、充值或钱包 Domain Ledger 共用原 GORM 事务,重复回调未发生状态变化时不重复写成功 Audit Event | `tb_payment``tb_order``tb_recharge_order``tb_agent_recharge_record`、钱包及唯一流水继续是支付、订单、充值和资金权威事实Audit Event 只解释操作者、回调来源、资源关系及前后状态,不替代支付状态、到账金额或渠道交易号 | 微信/富友真实预下单、代理充值微信/支付宝查单及所有已识别的微信/支付宝/富友回调逐次写 Integration Log使用稳定 `trigger_series+attempt`、支付单号 correlation 和渠道交易号幂等;成功回调仅在内部状态真实变化时标记 `state_changed`。支付宝 WAP URL 由本地签名生成Integration Log=N/A当前没有富友主动查单实现登记 N/A不虚构外部尝试 | 支付确认后既有佣金、套餐恢复、自动购包及代理充值入账 Outbox 保持原链路Audit Event 和 Integration Log 均不替代 Outbox。个人/代理充值完整创建至入账、钱包资金专项分别留给 7.67.9,本切片不修改渠道协议、金额校验、价格、佣金、套餐激活、钱包算法或状态机 |
| 个人资产充值与代理在线/线下充值 | 个人资产充值继续以 `payment.create/confirm/fail` 记录支付生命周期,并补齐真实个人客户、卡/设备、资产钱包和充值单资源;代理充值使用 `agent_recharge.create/credit/close` 记录线下申请、审批终态、在线/线下真实入账和关闭,支付事件补齐提交账号、目标店铺及主钱包。支付回调使用 `external_system/callback`,主动恢复使用 `scheduled_job/scheduler`Outbox 入账和自动购包使用 `system_task/worker`,不伪造最初提交人;重复支付、重复审批和重复入账未改变事实时不重复写成功事件 | `tb_recharge_order``tb_agent_recharge_record``tb_payment``tb_asset_wallet`/`tb_agent_wallet` 及唯一成功流水继续是充值与资金权威事实;成功 Audit Event 与充值状态、钱包余额、唯一流水及必要 Outbox 共用原 GORM 事务,审计失败回滚业务。`asset_recharge.auto_purchase` 与自动创建订单、钱包扣款流水、Payment、套餐权益和充值单自动购包状态同事务最终失败状态同样与 failed 审计同事务 | 微信、支付宝、富友预下单、回调和代理主动查单沿用 7.4 的逐次 Integration Logunknown 只表示外部结果未确认,不推进充值或钱包事实,也不伪造成功 Audit Event。线下申请创建和本地钱包入账不外呼Integration Log=N/A企微提交、终态同步与主动恢复继续由审批链 Integration Log 负责 | 代理在线支付确认继续写 `agent_recharge.payment_confirmed.v1`,由 Outbox 消费者幂等入账;线下申请继续写审批提交 Outbox审批通过后同事务写钱包 credited Outbox个人资产充值到账后沿用自动购包 Asynq自动购包继续写观测 Outbox。旧线下人工确认的账号 operation log 裸 goroutine 已停止;不新增充值渠道,不改变金额、钱包、审批、套餐激活或自动购包规则 |
### `deliver-july-iteration-confirmed-scope` 任务覆盖映射
- 1.1 对应“换货迁移套餐在原订单退款后失效”1.21.4 对应“订单渠道、资产标识、提交人与实名筛选”1.5 对应“换货创建前未终结退款拦截”。
- 2.12.4 分别对应店铺登录限制、实名策略、下架套餐续费、支付方式配置及后端校验。
- 3.13.3 分别对应物流换货提醒、主钱包低余额提醒、套餐临期提醒。
- 4.14.6 分别由企业微信应用、成员绑定、场景模板、默认发起人与提交、加密回调、主动恢复六行覆盖。
- 5.15.3 分别由员工线下代充值、退款企微终态、旧审批入口发布切换三行覆盖。
- 6.16.6 分别由批量订购、三组业务导出、IoT 卡限速、设备批量分配六行覆盖。
- 0.1、1.6、7.1、7.37.5 只产生证据、API 契约、静态检查或联调文档,不运行生产入口,因此 Audit Event、Domain Ledger、Integration Log 与 Outbox 均为 N/A7.2 即本基线维护动作。
## 旧 Writer 与旧表写入口清单
### 旧账号审计
- contract 结果:旧 Writer、Store、生产装配和全部借用旧账号日志的调用已删除`tb_account_operation_log` 表及存量数据原样保留,不回填、不转换、不接入统一 Query。
- 已切换入口:账号创建、基础资料更新、独立启停、软删除、管理员改密、本人改密、企微绑定及后台登录/登出已改用统一 WriterPostgreSQL 账号安全事实与审计同事务,登录/登出审计为提交后 best-effort失败不撤销 Token 也不改变原认证结果;刷新保持原单次刷新协议,不因审计重写。
- 角色创建/更新/启停/删除/默认信用、权限创建/更新/删除及角色权限分配/移除已切换统一 Writer角色、权限和关联变化与 Audit Event 同一 GORM 事务,批量配置不再逐项自动提交,权限快照保存 code/name 和资源级 before/after。
- 账号角色分配/移除及店铺默认角色分配/移除已切换统一 Writer账号或店铺为主要资源实际变化角色保存 ID/name/type/status 与分配前后值,关系变化与审计共用同一 GORM 事务;权限缓存在提交后 best-effort 失效Redis 失败不回滚业务。账号两处旧 operation log 写入已移除;店铺侧原本不存在旧账号日志写入。
- 店铺创建与基础资料变化已切换统一 Writer创建事件保存店铺编码、名称、上级和层级并与店铺、初始账号、默认角色及钱包初始化共用原有事务更新事件只记录实际变化的基础资料状态、业务员和 C 端登录限制留给 5.6。父子层级仍仅在创建时按既有七级规则确定,相关入口原本不存在旧账号日志写入。
- 店铺状态、业务员归属、C 端登录限制及删除已切换统一 Writer混合 PUT 按实际字段差异分别记录 `shop.enable/disable``shop.update_business_owner``shop.update_client_login_limit`,主体投影只保存安全结论;删除与账号禁用、账号资源变化及审计使用同一 GORM 事务,相关缓存在提交后 best-effort 失效。`Service.Enable/Disable` 当前无生产调用方,生产启停仍由 Update 状态字段承载;这些入口原本不存在旧账号日志写入。
- 企业创建、基础资料、状态和账号改密已切换统一 Writer分别使用 `enterprise.create``enterprise.update``enterprise.update_status``enterprise.update_password`,企业为主要资源,归属店铺为引用资源,实际企业账号为受影响资源;成功审计与企业/账号事实共用 GORM 事务,改密仅保存 `credentials_configured/state` 安全事实,不借审计改变原令牌行为。普通企业列表保持 N/A资产授权明确留给 5.8/5.9;这些入口原本不存在旧 operation log 写入。
- 企业卡授权、回收和授权备注已切换统一 Writer分别使用 `enterprise_card.allocate_cards``enterprise_card.recall_cards``enterprise_card.update_record_remark`企业为主要资源owner shop 为引用资源,实际变化的 IoT 卡和授权记录为受影响资源;授权事实与 Audit Event 共用 GORM 事务,重复有效授权不伪造变化。卡资源仅保存 `subject_result`安全结论,授权记录及备注保持 `internal_only``BatchAuthorize``RevokeAuthorizations` 无生产调用方、`AllocateCardsPreview` 为普通读取,均登记 Audit Event N/A。设备授权留给 5.9,本切片不改变卡授权有效性规则,也不引入第二套 Writer。
- 企业设备授权与回收已切换统一 Writer使用 `enterprise_device.allocate_devices``enterprise_device.recall_devices`企业为主要资源owner shop 为引用资源,实际变化的设备、设备授权、随设备处理的绑定卡及卡授权为受影响资源,实际卡槽绑定仅作为引用快照。授权创建与 Audit Event 共用 GORM 事务并锁定设备与当前卡槽绑定;回收改为事务内行锁和条件更新,按事务内真实命中项返回计数,不再调用持有独立 `db` 的 Store 方法形成伪事务。Service 边界显式拒绝空筛选和非法选取模式,参数错误不写 Audit Event企业/设备越权统一同错,零成功及并发全项冲突使用独立短事务写 `denied`。企业账号被明确拒绝,平台/代理继续复用 `CanManageEnterprise`,代理设备范围保持既有“仅本店设备”规则;设备与卡仅保存 `subject_result`,授权记录与卡槽绑定保持 `internal_only`。本切片不改变 1-4 卡槽绑定规则,不停止设备或卡的旧资产 Writer对应后续 6.x 用例)。
- 个人客户资料、手机号与微信主体已切换统一 Writer使用 `personal_customer.update_profile``personal_customer.bind_phone``personal_customer.change_phone``personal_customer.update_wechat_identity`,个人客户为主要资源,实际手机号或 OpenID 关系为受影响资源;资料更新、手机号绑定/换绑、客户或 OpenID 实际创建/同步与 Audit Event 共用 GORM 事务已识别客户后的业务拒绝或失败使用独立短事务。actor/source 固定为真实 `personal_customer/personal_api`,主体投影为 Registry 白名单约束的 `subject_detail`验证码、JWT、Cookie 和 Redis Token 不进入审计。重复微信登录且资料/OpenID 无变化不写资料事件,普通 `GetProfile`、资产令牌签发、登录 Token 签发与读取保持 N/A。
- 个人客户资产关系已切换统一 Writer使用 `personal_customer.bind_asset``personal_customer.unbind_asset``personal_customer.migrate_asset_binding`,个人客户为主要资源,实际新增、删除或迁移的 `tb_personal_customer_device`/`tb_personal_customer_iccid` 绑定为受影响资源,卡或设备以稳定标识快照进入同一事件。绑定沿用真实 `personal_customer/personal_api`,换货迁移和旧资产重置解绑沿用真实后台账号上下文;所有成功事件与原绑定写入、换货迁移或清理共用既有 GORM 事务,幂等绑定及无有效迁移记录不伪造成功事件。本切片不改变资产校验、首次绑定售出、换货资金/套餐迁移或无虚拟号旧资产重置规则。
- IoT 卡身份生命周期已切换统一 Writer实际导入落库使用 `iot_card.create`,每张新增卡与 `tb_asset_identifier`、Audit Event 共用原批次 GORM 事务actor/source 固定为真实 `system_task/worker`,以导入任务单号关联链路;已存在卡不写成功事件,导入任务创建及任务级根事件仍留给 8.3。单卡、批量删除分别使用 `iot_card.delete``iot_card.batch_delete`,实际删除卡与根子事件共用事务,缓存失效和轮询回调保持提交后执行,对应旧资产删除日志已停止。卡快照保存 ID、ICCID、VirtualNo、MSISDN、运营商、店铺、系列和 generation当前没有独立卡创建或基础资料更新生产入口后者登记 N/A。本切片不迁移分配/回收/系列、状态、实名、限速或 Gateway 命令。
- IoT 卡分配、回收和系列绑定已切换统一 Writer分别使用 `iot_card.allocate_batch`/`iot_card.allocate``iot_card.recall_batch`/`iot_card.recall``iot_card.series_binding_batch`/`iot_card.series_binding` 根子动作;实际卡归属、原有本地状态、`tb_asset_allocation_record``series_id` 更新与 Audit Event 共用原 GORM 事务,审计失败回滚业务,已识别资源后的拒绝/失败使用独立短事务。分配记录继续作为 Domain Ledger卡子事件关联来源/目标店铺、套餐系列以及实际存在的设备和卡槽绑定;绑定设备导致分配/回收拒绝时只记录真实既有关系不修改设备或绑定。缓存失效和轮询回调保持原提交后顺序对应三组旧资产操作日志已停止Integration Log、Outbox 均为 N/A本地事务不调用外部系统且无新增可靠副作用不迁移 6.3 的卡状态命令、实名、限速或 Gateway 行为。
- 设备身份生命周期已切换统一 Writer设备导入 Worker 使用 `device.create`actor/source 固定为 `system_task/worker`correlation 使用导入任务单号;每台设备的主表、资产标识、既有卡槽绑定与卡设备号快照、设备钱包及设备 Audit Event 保持在原单行 GORM 事务,审计只关联设备资源,不提前迁移卡槽语义。平台单删使用 `device.delete`,现有解绑、设备软删、资产标识清理和成功 Audit Event 同事务,失败/拒绝在业务未落地后写独立短事务;对应 `AssetAuditOpDeviceDelete` 调用已归零。设备快照保存 ID、VirtualNo、IMEI、SN、名称、型号、类型、制造商、店铺、系列和 generation当前不存在设备基础资料更新或批量删除生产入口均登记 N/A不为未来入口创建 Action 或 Service。导入任务创建的旧任务级审计仍留给 8.3;本切片不迁移状态、实名策略、分配回收、卡槽资源或 Gateway。
- 设备归属与策略已切换统一 Writer后台与 CSV Worker 共用 `device.allocate_batch`/`device.allocate``device.recall_batch`/`device.recall``device.series_binding_batch`/`device.series_binding`,实名策略使用 `device.realname_policy_batch_update`/`device.realname_policy_update`。分配、回收的设备与实际绑定卡归属/状态、分配记录和 Audit Event 共用 GORM 事务,系列与实名策略事实亦与审计同事务;子事件关联真实来源/目标店铺、分配记录、前后套餐系列、实际绑定卡及当前有效卡槽。已识资源的全拒绝和业务回滚失败使用独立短事务,二次失败保留原业务错误并记录 critical部分成功只为实际变化设备写 success 子事件。三组旧资产操作审计及 CSV 专用事实双写已停止;企业设备授权/回收已由 5.9 的 `enterprise_device.*` 覆盖,本切片登记 N/A不重复迁移。Integration Log 与 Outbox 均为 N/A均为本地事务且无新增可靠副作用设备外部命令明确留给 6.6。
- 设备外部命令已切换统一 Writer后台设备停复机、后台/个人 Wi-Fi、后台切卡模式以及后台/个人/OpenAPI 重启和重置均在共享设备 Service 接入。每次真实 Gateway HTTP 尝试写 Integration Log保留原重试与退避超时记录 unknown。停复机只为实际变化卡在原状态事务内写 `device.stop`/`device.start`,并关联入口设备、目标卡和现有 binding其他命令无同步内部字段变化Audit Event 只记录已下发、失败或结果未知的外部命令事实。Wi-Fi 密码不进入 Audit/Integration当前 `enabled` 未实际下发登记 N/A当前卡切换由后续卡槽关系切片覆盖。上述六组旧资产 operation log 调用已停止。
- 设备卡槽关系已切换统一 Writer后台绑卡/解绑分别使用 `device.bind_card``device.unbind_card`,平台后台、个人端和代理 OpenAPI 共用的当前卡切换使用 `device.switch_current_card`。设备、目标卡、旧/新当前卡和实际相关 binding 均进入独立资源时间线binding 快照及 before/after 保存 `slot_position/is_current`;设备导入创建 binding 和删除设备批量解绑则在原 `device.create/delete` 事件中补齐每张卡与 binding不另造重复动作。绑卡创建、解绑及切卡本地 `is_current` 与 Audit Event 共用 GORM 事务,审计失败回滚本地事实。切卡只允许当前设备有效绑定卡,每次 Gateway HTTP 尝试写独立 Integration Log超时或本地收口失败不伪装成功成功后仍保留原 Card Observation 分发校准真实当前槽位。三组旧资产 operation log 调用已归零;本切片不迁移设备/卡其他状态机,也不改变卡设备虚拟号提交后 best-effort 维护。
- 卡换货完整用例已切换统一 Writer物流创建、个人客户填写收货信息、后台发货、完成、取消和换出旧卡转新分别使用 `exchange.card.create``exchange.card.submit_shipping_info``exchange.card.ship``exchange.card.complete``exchange.card.cancel``exchange.card.renew`;直接换货创建即完成,只记录一次完成事件。成功事件与原换货单、卡状态、客户绑定迁移、资产钱包和流水、套餐权益及通知 Outbox 共用既有 GORM 事务,审计失败回滚业务;已识别换货单或旧卡后的拒绝/失败使用独立短事务并保留原错。完成事件分别关联换货单、旧/新卡 ICCID+VirtualNo、店铺、实际客户绑定、旧新钱包、迁移流水和实际迁移套餐权益客户绑定仍保留独立 `personal_customer.migrate_asset_binding` 事件,钱包流水和套餐权益仍是 Domain Ledger。个人收货资料、内部备注不进入审计主体仅看到安全结果旧卡转新为 `internal_only`。换货不调用外部系统Integration Log 为 N/A物流创建通知继续使用既有 Outbox。本切片不改变钱包迁移、PCI 解绑、套餐、资产归属或换货状态规则。
- 设备换货完整用例已切换统一 Writer物流创建、个人客户填写收货信息、后台发货、完成、取消和换出旧设备转新分别使用 `exchange.device.create``exchange.device.submit_shipping_info``exchange.device.ship``exchange.device.complete``exchange.device.cancel``exchange.device.renew`;直接换货仍只记录一次完成事件。成功事件继续与原换货事务、通知 Outbox、客户绑定、钱包/流水和套餐权益共用同一 GORM 事务,失败或拒绝使用独立短事务。完成事件关联换货单、旧/新设备 VirtualNo+IMEI+SN、店铺、实际客户绑定、旧新钱包、实际迁移流水和套餐权益并逐张关联旧/新设备当前有效绑定卡及 `device_sim_binding` 的 slot/is_current。现有业务不会在设备换货时迁移卡槽因此绑定卡和卡槽按真实状态记录为 reference不伪造变化客户绑定、钱包及套餐权益仅在实际变化时记录 affected。客户绑定独立事件、Domain Ledger、Integration Log N/A 和通知 Outbox 边界保持不变;本切片未修改设备卡槽、钱包、套餐、资产归属或换货状态规则。
- 套餐配置与授权已切换统一 Writer套餐系列使用 `package_series.create/update/delete/update_status`,套餐商品使用 `package.create/update/delete/update_status/update_shelf_status`,店铺套餐上下架、零售价和生效条件分别使用 `shop_package.update_shelf_status``package.update_retail_price``shop_package.update_expiry_base`,系列授权使用 `shop_series_grant.create/update/manage_packages/delete`。批量套餐分配与批量成本价调整分别使用 `shop_package.batch_allocate`/`shop_package.allocate``shop_package.batch_update_pricing`/`shop_package.update_pricing_item` 根子事件;全量价格锁拒绝为 `denied`,成功与拒绝混合为 `partial`,未实际变化或已存在而跳过的资源不伪造成功子事件。系列、套餐、店铺、系列授权、套餐授权和价格历史均作为独立资源进入各自时间线,配置与价格 before/after 只记录本次相关字段;成功事件与原配置、授权及价格写入共用 GORM 事务,已识别资源后的拒绝或回滚失败使用独立短事务并保留原业务错误。`tb_shop_package_allocation_price_history` 继续是价格变化的 Domain LedgerAudit Event 不替代它Integration Log 与 Outbox 均为 N/A本切片仅本地配置事务不发生外部交互或可靠异步副作用`shop_package_batch_allocation` 借用旧账号 operation log 的写入已停止,原上架、直属下级授权、佣金天花板、成本价锁定、赠送套餐和分配规则保持不变;套餐购买及 `package_usage` 权益生命周期明确留给 7.27.3,不在本切片迁移。
- 套餐权益生命周期已切换统一 Writer实际激活、到期及加油包级联失效、流量扣减、日/月/年重置、退款精准失效和按资产失效分别使用 `package_usage.activate/expire/deduct_traffic/reset_traffic/invalidate_refund/invalidate_asset`,只在状态条件更新或真实数值变化命中时写 success重复任务和无变化分支不伪造事件。`package_usage` 为主要/受影响资源,关联订单、套餐商品、当前卡或设备以及退款单均作为独立 reference 资源进入各自时间线;成功事件与 `tb_package_usage` 及每日流量详单 Domain Ledger 共用原 GORM 事务审计失败回滚业务已定位权益后的事务失败使用独立短事务并保留原错。Scheduler 使用真实 `scheduled_job/scheduler`Asynq、Outbox 消费和旧退款异步后处理使用真实 `system_task/worker`,人工实名激活保留 HTTP 账号 actorOutbox 消费以当前 envelope EventID 作为直接 parent沿用既有 request/correlation。退款审批标准 Outbox 同样把决策 EventID 传播为后处理 parent。换货完成继续复用 7.1 已有的同事务完成事件,不重复新增套餐迁移动作,并补齐迁移权益的激活/到期等快照以及独立订单、套餐引用;`tb_package_usage` 仍是权益权威事实。流量观测 Outbox 继续承担可靠传递Audit Event 不替代 Outbox套餐生命周期本地写不产生外部请求Integration Log 为 N/A。`InvalidateAllPackagesByAsset` 当前没有生产调用者,登记为已接好审计但生产覆盖 N/A不借本任务新增“资产停用即权益失效”规则既有套餐列表 Query 保持 N/A。`fix-package-activation-starvation` 的孤儿 CTE、每载体一个名额、同步恢复和两事务接续设计均作为独立专项修复保留本切片不改其业务规则。
- 订单生命周期已切换统一 Writer后台创建与代购、C 端普通购买、代理 OpenAPI 每笔购买、手工取消、待支付订单钱包支付及计划任务过期关闭分别使用 `order.create/cancel/wallet_pay/expire_close`。账号、个人客户、OpenAPI、批量 Worker 和 Scheduler 均保留真实 actor/source订单为主要资源买家、卡或设备、套餐、实际钱包/流水及 Payment 为独立关联资源,金额、支付状态、方式和购买角色保存为快照。成功事件与订单、明细、资金、支付、套餐权益及既有 Outbox 共用原 GORM 事务,审计失败回滚业务;拒绝和事务失败保留原错误并写独立短事务,幂等无变化分支不伪造成功。支付渠道 Integration Log 留给 7.4,代理及资产钱包自身资金动作分别留给 7.7/7.9OpenAPI/CSV 批量根事件留给 8.3;本切片未修改价格、佣金、套餐激活、钱包算法、授权或订单状态机,普通订单 Query 保持 N/A。
- 支付外部与内部终态已接入统一边界Payment 创建、渠道明确关闭和回调确认分别使用 `payment.create/confirm/fail`,没有 Payment 的旧订单回调使用 `order.online_pay`;支付单、订单或充值单、渠道交易号以及回调实际变化的钱包/流水进入同一事件,成功审计与对应 Domain Ledger 共用原 GORM 事务,重复回调不伪造成功事件。微信/富友真实预下单、代理充值微信/支付宝查单及微信/支付宝/富友已识别回调写 Integration Log支付宝 WAP 本地签名和当前未实现的富友主动查单均明确 N/A。Integration 使用支付单号 correlation回调用渠道交易号幂等结果未知不伪装失败或成功本切片未重构渠道协议也未修改价格、佣金、套餐激活、钱包、授权、金额规则或状态机充值与资金专项审计仍由 7.67.9 收口。
- 个人资产和代理充值已切换统一 Writer个人资产充值的 `payment.create/confirm/fail` 事件补齐个人客户、卡/设备、充值单、资产钱包和唯一流水;代理线下申请、真实入账及拒绝/关闭分别使用 `agent_recharge.create/credit/close`关联提交账号、目标店铺、审批实例、支付单、主钱包和唯一流水。外部回调、主动恢复、Outbox 消费分别保留 `external_system``scheduled_job``system_task` actor重复终态不伪造成功。自动购包使用 `asset_recharge.auto_purchase`,与订单、支付、钱包扣款流水、套餐权益及充值单自动购包状态同事务,最终失败状态同样原子记录;既有 Integration Log、审批/入账 Outbox、观测 Outbox 和自动购包 Asynq 边界不变。旧线下人工确认的账号 operation log 裸 goroutine已停止本切片不新增渠道也未修改金额、钱包、审批、套餐激活、佣金或自动购包规则。
- 代理主钱包订单资金已切换统一 Writer直接扣款使用 `agent_wallet.order_debit`,预占、释放和完成分别使用 `agent_wallet.order_reserve/order_release/order_complete`;订单为主要资源,主钱包、预占事实及实际成功流水为受影响资源,钱包记录 balance/frozen_balance 前后值流水保留唯一业务引用。Audit Event 与既有行锁、乐观锁、状态条件、唯一流水和钱包 Outbox 共用原事务,写入失败回滚全部业务事实;订单事务整体失败后按已尝试的钱包动作写独立短事务,重复扣款或重复预占终态不伪造成功事件。完成预占由 `order_complete` 同时关联扣款流水,不再重复生成 `order_debit` 审计。当前生产只有直接扣款和取消订单 release 调用freeze/complete Application 接缝暂无生产调用者,本任务只接入审计,不新增调用、不修改钱包、订单、套餐、佣金、充值、退款或信用额度规则。
- 代理主钱包正向及回退资金已完成专项收口:充值继续复用 7.6 的 `agent_recharge.credit`,退款继续复用 7.5 的 `refund.approve`,两者均已在一条业务事件中关联主钱包、原流水/新流水和余额前后值,不新增同义钱包事件。人工调整使用 `agent_wallet.adjust_balance`,在既有 Posting/Outbox 事务内关联唯一调整流水并强制记录原因;当前无生产入口,只接好现有 Application 能力,不新增接口。实际信用额度更新使用 `agent_wallet.change_credit`,主钱包为主要资源、店铺为引用资源,保存余额/冻结余额不变和信用字段/version 前后值;成功审计失败回滚信用更新,已识别钱包后的拒绝/失败使用独立短事务并保留原错。Integration Log 均为 N/A本切片未修改充值、退款上限、钱包算法、信用占用、审批、佣金或资产钱包规则。
- 卡/设备资产钱包资金已完成专项收口:充值复用 `payment.confirm`,扣款复用 `order.wallet_pay`,退款复用 `refund.approve`,换货迁移复用 `exchange.card.complete/exchange.device.complete`,不新增同义钱包动作。四类成功事件均在原业务事务内关联卡的 ICCID/VirtualNo 或设备的 VirtualNo/IMEI/SN、资产钱包、充值/订单/退款/换货单及唯一流水,并保存余额前后值;充值事件只保留一条受影响钱包资源,订单扣款的钱包和流水明确标记为 affected。支付、订单、退款状态条件及换货状态机继续阻止重复业务键或重复终态伪造成功无余额迁移不创建流水钱包流水继续作为 Domain Ledger。充值渠道外部尝试沿用 Integration Log其余本地钱包动作 N/A本切片未修改钱包余额/冻结/乐观锁、退款上限、换货迁移、套餐、客户绑定或代理主钱包规则。
- 佣金与提现状态机已切换统一 Writer订单 Worker 使用 `commission.calculate` 记录真实 `system_task/worker`、订单佣金状态结果、全部佣金记录、归属店铺和套餐系列;每笔自动入账及待审人工入账使用 `commission.credit`,关联佣金记录、订单、店铺、系列、佣金钱包及实际存在的钱包流水和余额前后值;待审人工失效使用 `commission.invalidate`。退款回扣继续只使用既有 `refund.invalidate_commission`,不重复造佣金失效事件。提现申请、通过、驳回分别使用 `commission_withdrawal.request/approve/reject`,提现单为主要资源,店铺、佣金钱包及冻结/扣除/解冻流水为独立资源,收款账户 JSON 不进入审计。成功事件与现有佣金、订单、钱包、流水和提现事实同事务,已定位订单、佣金记录或提现单后的拒绝/失败使用独立短事务;幂等完成订单不伪造重复成功。现有“待审佣金人工入账”业务只更新佣金记录和钱包、不创建钱包流水,本切片按真实事实关联钱包但不伪造 Domain Ledger统计 Query、佣金公式、阶梯规则、提现金额/手续费、冻结算法和审批状态机均未修改。Integration Log 与 Outbox 为 N/A这些链路没有外部调用或新增可靠副作用
- 轮询配置与人工动作已切换统一 Writer轮询配置创建、更新、删除和启停使用 `polling_config.create/update/delete/update_status`,并发配置更新与计数重置使用 `polling_concurrency.update/reset`,告警规则创建、更新和删除使用 `polling_alert.create_rule/update_rule/delete_rule`;成功事件与对应 PostgreSQL 配置事实共用 GORM 事务审计失败回滚配置写入。Redis 并发计数重置无法与 PostgreSQL 原子提交,审计失败时恢复重置前计数;人工单卡去重键在日志/审计事务失败或队列写入失败时移除,避免阻断原有重试。
- 单卡、批量、条件筛选人工触发和取消分别使用 `polling_manual_trigger.trigger_single/trigger_batch/trigger_by_condition/cancel_trigger`,记录真实后台账号、手动任务和实际卡资源;配置重名、每日触发上限、重复入队、越权取消和已结束任务取消等已定位资源的拒绝写独立短事务,二次失败保留原业务错误并记录 critical。`tb_polling_manual_trigger_log` 继续承担进度、结果与历史查询,不被 Audit Event 替代或停写;审计不复制 `CardIDs`、条件正文、通知渠道正文或其他安全凭据,只保存任务类型、触发方式、数量、状态及“条件/通知渠道是否配置”等安全事实。
- 实名、流量和卡状态轮询的每次真实 Gateway 尝试继续写 Integration Log套餐/保护期轮询自身不伪造 Gateway 尝试,实际停复机复用共享 `StopResumeService` 的 Audit/Integration 边界。轮询配置、并发状态、告警历史、人工任务状态/历史和监控页面等普通运行查询均为 N/A通知投递、任务 ledger、Audit Event 与 Integration Log 保持独立事实。`polling_cleanup` 数据清理配置未包含在 8.5 明确边界,本轮不借轮询审计扩展其 CRUD 或手动清理动作,继续保留在覆盖清单等待对应显式切片。
- 外部 Callback 已按当前生产路由收口:微信/支付宝/富友支付回调继续复用 7.4 的支付、订单和充值事务审计,企微审批回调继续复用 8.1 的权威终态审计;电信、移动、联通实名成功回调在共享 `ApplyCardObservation` 事务中使用 `iot_card.realname_callback_sync`,真实 actor 为各运营商 `external_system/callback`,关联 IoT 卡和入站 Integration Log。重复支付、重复审批、重复实名及无状态变化只保留 Integration Log不伪造成功 Audit Event联通解除实名仍仅留痕且不改变本地实名事实。本切片不修改支付、运营商或企微协议。
- 当前 31 个 Asynq Worker 已按 8.7 逐项复核:`iot_card:import``device:import``order_package:invalidate``asset_package:batch_order``commission:calculate``package:first_activation``package:queue_activation``order:expire``notification:cleanup``auto_purchase:after_recharge``wecom:approval:sync``wecom:approval:recovery``agent_recharge:recovery` 已复用前序纵向切片的统一 Audit Event本切片新增 `card_observation:series``polling:realname/carddata/card_status``system_task/worker` 上下文,仅在实名、流量、网络或设备字段/当前卡槽实际变化时分别写 `iot_card.worker_realname_sync``iot_card.worker_traffic_sync``iot_card.worker_network_sync``device.worker_observation_sync`,并关联对应 Gateway Integration Log。`polling:package/protect` 不另造轮询动作,实际停复机继续复用 `iot_card.auto_stop/auto_start/auto_stop_reason_update`。上述链路传播 request/correlation/parent重试失败写 failed 短事务,无实际变化仅保留 Integration Log 或任务运行事实,不伪造 success。
- Worker N/A 与后续边界:`email:send` 仅模拟邮件投递;`export:dispatch/shard/finalize` 仅做导出技术装配;`commission_stats:update/sync/archive` 仅维护 Redis/PostgreSQL 统计投影;`polling:alert_check` 仅生成告警运行事实;`polling:data_cleanup` 仅执行既有轮询数据清理;`package:expiry_reminder` 仅生成可靠通知 Outbox`daily_traffic:flush` 仅把 Redis 日流量 Domain Ledger 落盘,均不重复创建 Audit Event。`outbox:deliver` 自身是可靠投递技术入口Relay/投递事实 N/A其各业务消费者是否形成新业务事实按任务 8.9 逐项收口,不在 8.7 提前迁移。Scheduler 仅投递或创建任务的边界留给 8.8。
- Scheduler 已按当前注册清单逐项复核:代理在线充值恢复、订单过期关闭和企微审批恢复在真实业务事实变化时使用 `scheduled_job/scheduler`;轮询 Scheduler 直接执行的套餐到期、后续权益接续、流量周期重置及套餐到期停机检查同样保留 `scheduled_job/scheduler` 操作者。套餐到期后的异步停机检查使用不受调度 tick 取消影响的原审计上下文,继续传播 actor、correlation 和 parent不伪造人工操作者。
- Scheduler N/A 与幂等边界Asynq 周期注册、轮询心跳、队列深度检查、分片/手动队列出队、重复调度的 `Unique` 去重与失败回队只是技术调度或任务事实,不写 Audit Event也不把后续 Worker 结果伪装成 Scheduler 成功。告警检查、轮询数据清理、通知保留清理、套餐临期提醒和日流量落盘继续按 8.7 的 Worker/Domain Ledger/Outbox 边界处理;重复调度依赖既有状态条件、领取租约、稳定事件 ID 和 Asynq `Unique`,无实际变化不伪造 success。Worker 消费逻辑未在 8.8 迁移。
- 当前 14 个 Outbox 事件注册、12 个消费者实现已按 8.9 逐项复核:企微审批提交终态、审批标准决策分发、卡实名/流量/网络变化后续处理、代理在线充值入账和三类站内通知生成会形成新的内部业务事实,均通过 `outbox:deliver` 入口取得 `system_task/worker` actor并沿用信封的 request/correlation/parent实际变化继续复用 8.1、7.2、7.6 和 8.4 已接入的同事务 Audit Event。状态条件、处理租约、稳定事件 ID、业务唯一键和通知 `CreateIdempotent` 保证至少一次投递不会伪造重复 success消费者返回成功只代表本次业务处理完成Outbox 的 delivered 状态仍是独立投递事实。
- Outbox 消费者 N/A 边界:卡观测序列请求仅幂等创建后续观测任务,代理主钱包预占/入账/退款消费者仅复核既有 Domain Ledger扣款消费者仅复核流水并按阈值幂等追加新的通知 Outbox均不把“校验通过、任务触发或二次投递成功”写成业务 Audit Event后续观测或通知实际改变业务事实时由对应 Worker/Application 自身写 Audit Event。Relay 的领取、入队、续租、delivered/failed、退避和重投保持技术投递事实不在 8.9 修改或审计化。
- request/correlation 组合时间线只按非空稳定 ID 精确读取 `tb_audit_event``tb_integration_log``tb_outbox_event`,以 `record_source` 保留 Audit、外部交互及可靠投递边界Outbox 只展示当前投递摘要,不把 delivered 解释为业务成功。Asynq 没有通用 PostgreSQL 历史表Query 仅从已落库的导入、批量购包、套餐失效、设备批量和导出任务资源生成 `asynq_task` 摘要,不扫描 Redis、不展示技术重试。订单、支付、退款、充值、钱包/流水、套餐权益、审批和佣金等只生成 `domain_ledger_ref` 稳定引用,金额与状态仍以业务表为准并留给 9.2 专业资金视角。Access Log 只返回 request ID 供开发检索,不读取日志文件;历史缺少 request/correlation/parent、直接 Audit 关联或稳定资源时通过 fidelity 标记原样降级,不按相近时间、相似资源或相同 correlation 猜测技术尝试。节点统一按发生时间、`record_source`、稳定节点 ID 升序排列。
- 资金调查时间线以平台只读 Query 组合 Audit Event、代理/资产钱包流水、代理钱包预占、订单、支付、退款、代理/个人资产充值、佣金、提现和审批当前业务事实;支持从店铺、钱包、订单、支付、退款、充值、审批、第三方交易号、操作者、时间或 correlation 中任一稳定条件进入,并在服务端解析已持久化关联,不要求前端补齐整条链路。节点按发生时间、`record_source`、稳定节点 ID 倒序分页,统一返回调查跳转引用;钱包流水的 `amount/balance_before/balance_after` 及各业务表金额字段明确标记为权威Audit Event 金额只作操作摘要,冲突时不改写历史事件并以对应 Domain Ledger 为准。平台身份复用统一审计 Query 的 SuperAdmin/Platform 后端校验,不增加店铺数据范围,也不提供资金重算、状态修改、导出或恢复能力。
- 风险调查视角只读聚合统一 Audit Event高/严重风险、涉及订单/支付/退款/充值/钱包/佣金等资金资源、安全类别,以及 `failed/denied/partial/unknown` 结果进入固定风险集合普通低风险成功事件明确排除。overview 在最长 31 天的显式时间范围内按风险、结果、action、来源和小时/日趋势聚合events 复用统一事件批量投影、稳定倒序分页及 `investigation_refs`可继续跳转事件、资源、actor 和 correlation。该视角不读取或修改业务状态不产生 Audit Event、Domain Ledger、Integration Log 或 Outbox也不提供处置工单、自动封禁、导出或恢复能力。
- 跨视角查询性能仅补已确认路径的 PostgreSQL B-tree保留事件时间、actor、scope、correlation 和资源时间线既有索引,补 action、result、risk、category、source 的稳定倒序分页索引,将 request/parent 索引补齐时间与 ID并为资源 type+id/key 到事件的反向关联补索引。全局、actor、资源和风险事件先分页事件 ID再批量投影事件与资源Integration 列表同样先分页 ID再批量读取列表字段不加载正文 JSON。第一阶段不增加 JSONB 任意搜索、Redis 结果缓存、月分区或冷热联合查询。
- 跨视角 HTTP 契约复用既有平台 `AuditHandler` 和生产/文档装配,仅新增 request、correlation、finance、risk 的只读 GET Handler/DTO/RouteSpec身份继续只取认证上下文未增加写路由、导出、处置、恢复或前端实现。前端导航文档逐行冻结 design 8.1-8.4 的源页面、前置接口、`response.data` 字段、入口可见条件、目标参数和降级规则,并以资产、订单、退款、钱包、通知、风险节点演示完整调用链。
- Audit Event 与 Event Resource 每日冷归档使用独立 `audit:daily:archive` Asynq 任务和 `tb_log_archive_run` 轻量账本:按 `Asia/Shanghai` 前一完整自然日、事件 `created_at` 半开区间分页读取,每行保存一个完整事件及其全部 `resources[]`,生成 JSONL+gzip、manifest 和 SHA-256对象 Key 按日期与 revision 稳定生成,上传后回读 metadata 核对大小、hash、事件数和资源数成功重复任务直接复用失败或对象不一致使用新 revision 且不覆盖旧对象。该基础设施任务不写业务 Audit Event不读取 Integration/Access/Domain Ledger/Outbox/旧 operation log不清理数据库也不向业务 Writer 注入对象存储;对象存储失败只更新归档账本并由 Asynq 重试,业务审计写入继续正常执行。
- Integration Log 冷归档复用同一对象存储、归档 Service 和 `tb_log_archive_run``integration:daily:archive``created_at` 保存前一自然日的结构化 JSONL+gzip 创建日快照;`integration:monthly:finalize` 在月初逐日按数据库当前内容重新生成并比较记录数与 SHA-256首次终结、内容变化或对象 metadata 不一致时创建新的不可变 revision旧对象不覆盖。月度复核仅把无 `pending` 记录且最终对象、manifest 均复核成功的日期标记 `is_final``pending`、对象损坏或复核失败会使任务失败并明确阻止后续清理。该切片不修改 Integration Writer、恢复语义或业务状态也不删除 PostgreSQL 数据、不提供对象存储查询/恢复接口。
- 月度留存清理使用 `audit:monthly:retention` Asynq 任务,在 `Asia/Shanghai` 每月 1 日 06:00 处理上一完整自然月:先补齐最后一日 Audit/Integration 归档并完成 Integration 最终 revision再逐日核对 ledger、manifest、对象 metadata、压缩对象实际大小/SHA-256 及数据库数量。全月硬门禁通过后仅按 Event Resource → Audit Event → Integration Log 顺序对 `tb_audit_event_resource``tb_audit_event``tb_integration_log` 以 1000 行有界批次执行 GORM 物理删除,并复用 `tb_log_archive_run.cleanup_started_at/cleaned_at` 断点续跑;对象存储归档和 manifest 长期保留。清理结果以 `retention_worker/system_task` 写当月 `audit.retention_cleanup` Audit Event资源为 `log_archive_month`Domain Ledger、Integration Log 新写、Outbox 均为 N/A因该事实是内部留存执行结果不是业务状态、外部交互或可靠投递。Access Log、订单/支付/退款/钱包等 Domain Ledger、Outbox、Asynq 运行事实、手动轮询、旧 operation log 及其他业务表明确不删除。
- 在线审计查询以 `tb_log_archive_run.cleaned_at/range_end` 作为真实清理边界:平台 Audit/Integration、request/correlation/finance/risk 及代理/企业活动响应统一返回 `retention{online_from,archived_before,timezone}`;缺省时间范围只查 PostgreSQL 在线窗口,显式早于或跨越边界返回 `CodeAuditDataArchived` 和当前边界。稳定事件或 Integration ID 只在在线库查找,不存在仍返回资源不存在;历史资源快照搜索和 Integration 尝试序列同样受边界限制。该 Query 切片不访问对象存储,不新增归档下载、恢复、冷热联合查询、导出或写路由,普通读取仍为 Audit Event/Domain Ledger/Integration Log/Outbox N/A。
- 留存灰度默认使用 `worker.audit_retention_cleanup_enabled=false`:月初 `audit:monthly:retention` 只读复核完整月 ledger、manifest、对象 metadata/大小/SHA-256、Audit 计数和 Integration 最终 revision并记录三类在线行数、manifest 数、校验耗时和预计 1000 行删除批次;不会写 `cleanup_started_at/cleaned_at`,也不会执行 DELETE。完整自然月可在显式确认的隔离测试数据库中按真实日界构造无需等待现实时间流逝dry-run 通过后仅在该测试环境启用清理,验证目标月三张日志表归零且月前/月后哨兵、其他业务事实和对象归档不受影响。2026-08-06 使用 `.env.local``junhong_cmp_test` 完成 `2001-02` 仿真56/56 归档成功、28/28 Integration final、最大 revision/attempt=2、压缩率 0.5047、dry-run 无清理断点、清理后目标月三表归零且 6 条边界哨兵保留、56 条账本清理断点完整并写入 1 条清理审计。生产开关仍保持关闭;该 Release/Observability 切片不产生 Domain Ledger、Integration Log 或 Outbox。
## 2026-08-06 最终 Registry 与覆盖门禁复核
- 业务复核692 个当前源码入口均进入显式清单;状态变更、资金、权限、关键配置、批量、多资源、设备卡槽、换货、自动入口及 5 组敏感读取均已在上方领域矩阵给出 Audit Event 或逐项 N/A 决定。39 个 Worker 注册语句对应 35 个唯一 TaskType重复注册来自对象存储可用/不可用两条互斥装配分支,不代表重复消费。
- 研发复核219 个 `AuditAction` 常量与 219 个 `actionsByCode` 注册项一一对应16 个兼容 `AuditOperation``actionsByOperation` 一一对应;生产使用未注册动作、动作字符串字面量均为 0。61 个资源类型常量与 61 个 Resource Registry 条目一一对应146 个资源角色常量均有生产引用,生产 `ResourceInput` 未使用资源类型或角色字符串字面量。Writer 对未知 action、未知 resource、主要资源不匹配及不完整关系保持 fail-closed。
- 查询复核:通用资源时间线直接以 Resource Registry 判定支持类型,不再维护独立 13 类白名单;资源搜索仍按第一阶段契约只开放卡、设备、店铺、订单和退款 5 类 resolver。统一 Query 不读取旧账号/资产 operation log。
- 外部与可靠链路复核78 个 Integration Log 调用点覆盖 `Start/Complete/RecordInbound/ClaimExpiredInboundPending`14 个 Outbox Consumer 注册点均显式登记Consumer 注册本身为技术装配 N/A实际状态变化沿用对应 Consumer/Application 动作Outbox 投递事实不伪装成业务成功。
- 安全复核:普通 GET 继续逐项 N/A企微明文应用凭据、资产实时状态、后台/个人实名链接、完成态导出任务详情等敏感读取保持返回前 fail-closed 审计。密码、验证码、Token、Secret、私钥、Cookie、签名 URL 和支付密钥不进入 Audit/Integration 或主体投影。
- contract 复核:旧 Writer 调用为 0旧账号表与旧资产表原样保留旧资产历史入口只读手动轮询 ledger 继续读写。扫描清单 692 项必填分类字段缺失为 0Audit Event N/A 无理由为 0静态扫描、gopls、全仓构建与 `git diff --check` 作为本 Change 禁止自动化测试约束下的完成证据。
## 2026-08-06 安全与身份发布门禁复核
- 身份边界:平台 Audit/Integration Query 仅允许 `SuperAdmin/Platform`,代理与企业即使通过通用后台认证也在 Query 层统一 fail-closed代理范围只取认证上下文中的自身及下级店铺企业只取认证上下文企业 ID并要求卡/设备授权 `revoked_at IS NULL AND deleted_at IS NULL`
- 主体投影:不支持资源类型与不存在/越权统一返回“无权限操作该资源或资源不存在”;活动投影返回前再次核验目标资源当前归属或有效授权。`internal_only` 不进入统计、列表和关联资源,`subject_result` 强制返回空 `subject_data`,只有 `subject_detail` 解码持久化白名单数据;主体 DTO 不包含 actor、risk、内部 before/after、Audit Event ID、request/correlation 或 Integration 内容。
- 平台完整性:平台事件详情继续完整投影已存业务 metadata、资源身份快照及各资源 before/after不对手机号、IP、ICCID、VirtualNo、金额和交易号执行展示掩码系统安全凭据仍由 Writer/Sanitizer 在持久化前删除。
- 凭据门禁:统一 Sanitizer 已覆盖驼峰字段名、裸 token/api/payment key 及凭据文本值Audit/Integration 标量同样在落库和历史响应投影前清理。`.env.local` 测试 PostgreSQL 只读抽样中Audit Event JSON、Audit Resource JSON、Audit 标量、Audit Resource 标量、Integration 标量、Integration 禁止键和 Integration 凭据值命中均为 0。历史 Integration 的 129 条初始正则命中全部是允许的 `token_present` 布尔安全事实,不包含 token 值。
- 能力面:`internal/routes/audit.go` 及生成的 `docs/admin-openapi.yaml` 中 15 条平台/代理/企业审计路径全部只有 GET未注册审计导出、对象存储归档查询/恢复、Integration 重试/补偿/修改/删除或 Audit Event 业务删除路由。旧资产 operation-logs 继续作为仅平台可读的独立历史白名单入口。
- 验证约束:本 Change 明确禁止新增、修改或运行自动化测试;本门禁使用敌对身份调用链静态复核、数据库只读抽样、路由/OpenAPI 扫描、全仓构建、gopls 与 `git diff --check` 作为完成证据。
## 2026-08-06 事务、幂等与跨链路发布门禁复核
- 同事务失败关闭:系统配置更新在同一 GORM 事务内完成业务写和 `WriteConfigChange`;代理主钱包扣款/入账在同一事务内完成条件更新、唯一流水和 Audit EventWriter 错误直接返回并回滚业务事务。Outbox 恢复、审批终态及其他高风险纵向切片沿用相同 `tx` 接缝,不使用提交后的补写冒充原子性。
- 失败短事务:统一 `Writer.RecordFailure` 仅在原业务返回后开启独立短事务,`fillFailureInput` 保留原 `AppError` code/message二次写失败只递增 `secondaryWriteFailures` 并输出含 action、资源、request/correlation 和原错误码的 critical 日志,不替换原业务错误。
- 批量根子:`AppendBatch` 在落库前拒绝负数、`success+fail>total`、子事件少于成功数或多于已处理数,并为子事件补齐稳定 parent/correlation。该门禁发现并修复 IoT 卡批量轮询开关原先缺少根/子 `EventID` 的生产缺口,现按请求批次和卡 ID 生成稳定 ID并以实际有效卡数计数。测试库只读核对中批量计数错误、非法结果、缺少/多个主要资源均为 0当前在线窗口没有带批次统计的根事件因此不伪造动态样本结论。
- Audit 链路:测试库中 `child_without_parent_online``child_without_correlation``parent_correlation_mismatch` 均为 0。跨事实 Query 分别读取 Audit Event、Integration Log、Outbox并以独立 `record_source` 投影Domain Ledger 和 Asynq 仅作为 `reference_only` 稳定引用,金额权威仍由资金业务表提供。
- Integration 技术序列:只读核对发现存量代理充值查单及卡观测记录存在重复 `trigger_series + attempt`。新写入已前向修复:自动 attempt 在序列级 PostgreSQL advisory lock 的同一短事务内分配;卡观测按 `series_id + sync_type` 区分不同 Gateway operation。历史数据不回填、不猜测详情保留每条真实 operation并以 `attempt_sequence_reliable=false` 明确重复、断档或混合 operation 的受限保真度。
- 幂等边界Audit Event 继续以稳定 `event_id` 冲突不重复写;资金使用业务唯一流水和状态/版本条件Outbox 保持独立至少一次投递状态。Audit、Integration、Domain Ledger 和 Outbox 之间只通过 request/correlation/parent、稳定业务 ID 或只读引用关联,没有把外部尝试、投递成功或审计摘要伪装成业务成功。
- 验证约束:未新增、修改或运行自动化测试;完成证据使用代表性事务源码调用链、测试 PostgreSQL 只读不变量查询、覆盖清单、OpenAPI、全仓构建、gopls 与 `git diff --check`
## 2026-08-06 迁移、性能、OpenAPI、归档留存与回滚发布门禁复核
- 迁移现状:`.env.local` 测试 PostgreSQL 的 `schema_migrations``205/dirty=false`Audit、Integration、归档账本关键增量索引已存在。共享测试库已有 Audit 和归档事实,未对 `public` 执行 down。
- 无事实 down/up在同一测试 PostgreSQL 的隔离 schema 中使用最小前置表结构执行 `000199`~`000205` up再按 `205→199` 逆序 down上行后目标表/列/索引存在,回滚后 Audit/归档表移除且 Outbox parent/订单预占列恢复。`000199.down` 自带事务并提交外层事务,隔离 schema 已显式删除且核对不存在;该注意项已写入操作手册。
- 性能观测:复用已完成 9.4 的分页 ID + 批量投影与索引证据;当前库只读 `EXPLAIN (ANALYZE, BUFFERS)`事件列表、资源时间线、Integration 列表、风险聚合执行时间分别为 `0.315ms/0.116ms/0.186ms/0.123ms`,均低于 50ms。当前 Audit 在线样本很小PostgreSQL 对部分路径选择顺序扫描Integration 已命中 provider 索引未因小样本增加缓存、分区或额外抽象。API P95/P99 沿用 9.4 完成证据及发布后 Access Log 阈值,本门禁不重复运行接口压测。
- OpenAPI`go run ./cmd/gendocs` 生成 `docs/admin-openapi.yaml`;运行时文档入口已生成 `logs/openapi.yaml`。两份制品均包含 15 条平台 Audit/Integration 及代理/企业资源活动路径。
- 归档留存:复用 10.5 的 `2001-02` 完整月证据56/56 归档成功、28/28 Integration final、最大 revision/attempt=2、压缩率 0.5047、dry-run 零清理断点,物理清理后目标三表为 0、6 条边界哨兵保留、56 条清理断点完整、1 条当月清理审计且对象/manifest 未删除。归档失败、缺日、pending、计数/SHA-256/对象 metadata 不一致均在 DELETE 前 fail-closed生产清理开关仍关闭。
- 回滚:现有归档手册已补充 contract 回滚 SOP 与全局监控阈值。业务回滚保留版本 205 结构、当前在线 Audit/Integration、全部 Domain Ledger/Outbox 和对象存储归档;只能回到旧 Writer 已停写的 contract 基线,不恢复旧 Writer不对已清理月份回填或伪造在线历史。
- 静态门禁:覆盖清单重新生成 692 项;全仓 `go build ./...`、已改 Go 文件 `gopls check``git diff --check` 通过。Go 只输出 module stat cache 无权限警告,构建退出码为 0。本 Change 未新增、修改或运行 `_test.go`;当前门禁按用户要求不再执行接口压测。
### 与审计接入分开保留的独立修复
- 企业、企业卡和企业设备的权限校验、空筛选防全量、批量边界、越权同错及企业设备 TOCTOU/真实命中计数作为独立安全与并发修复保留,不视为审计所需的业务重构。
- 手机号绑定/换绑的行锁和事务内二次复检、账号状态与代理越权校验、管理员账号改密后撤销 Token 作为独立修复保留;企业账号改密不扩展同样的 Token 行为。
- 角色/权限变化和店铺删除后的权限缓存清理能力作为独立修复保留,但只在数据库提交后 best-effort 执行,不让 Redis 失败反向回滚业务事实。
- 支付配置和员工线下充值的外层裸 goroutine、旧账号 Writer 及旧资产 Writer 的异步写入均已归零。
- 迁移责任04、07、0819 号票验证生产装配和直接旧表写入归零。
### 旧资产审计
- contract 结果:旧资产 Create/Writer、全部业务调用、裸/双重 goroutine 和 Worker 装配已删除;卡/设备停用、轮询开关及套餐人工调整已切换统一 Writer业务事实与成功审计同事务已识别资源后的失败/拒绝使用独立短事务。
- 历史只读白名单:`internal/service/asset_audit/``internal/store/postgres/asset_operation_log_store.go``internal/handler/admin/asset.go``internal/routes/asset.go``internal/model/dto/asset_operation_log_dto.go` 仅保留旧资产历史查询;主进程只注入只读 Store/ServiceWorker 不再装配旧资产 Store。
- `tb_asset_operation_log` 表及存量数据原样保留,不回填、不转换、不接入统一 Query生产业务不再新增记录。
- 迁移责任05、06、0919 号票验证生产装配和直接旧表写入归零。
### 旧手动轮询日志
- 状态与写入:`internal/service/polling/manual_trigger_service.go``internal/store/postgres/polling_manual_trigger_store.go``internal/model/polling.go`
- 装配与接口:`internal/bootstrap/services.go``internal/bootstrap/stores.go``internal/handler/admin/polling_manual_trigger.go`
- 当前继续承担运行状态、进度、结果和历史查询8.5 仅为人工触发/取消补充统一 Audit Event不得停写、删除或以 Audit Event 替代该 ledger最终旧写护栏必须将其列入显式白名单。
## 评审门禁
本轮已按当前代码完成以下三视角复核;后续源码入口、事务、敏感字段或可见性变化会使覆盖门禁失败并要求重新复核:
- 业务评审逐入口业务所有者、资源、Domain Ledger 与 N/A 理由准确,没有改变已评审业务范围。
- 研发评审:事务边界、失败策略、旧 Writer 清单、动作编码和测试接缝能由对应迁移票落地。
- 安全评审:风险等级、敏感字段策略、拒绝/失败覆盖和外部正文摘要策略完整。
后续评审发现错误时应修改对应显式条目和生成分类规则,并重新运行覆盖门禁;禁止仅手改统计数字。

File diff suppressed because it is too large Load Diff