## Context

### 当前状态

七月标准评审稿覆盖 28 条技术/业务线，但实施信息分散在 28 份相关 PRD、121 张七月业务/公共基础 Tickets、22 张全局审计 Tickets、代码、迁移、文档和提交记录中。现有状态存在四类偏差：

1. **完成状态漂移**：TECH 公共基础 12/12 与 UR55 5/5 已完成；UR45 代码已落地但两张 Ticket 仍为 `ready-for-agent`；UR46 四张票仅标记“后端 done”；UR60、UR86 后端已完成但仍有人工作与历史抽样；顶层 PRD 状态普遍未同步。
2. **依赖不可执行**：公共通知、UR37、UR48、UR49 存在不存在文件、尚未拆票占位符或标题漂移；多个需求仍把未完成的全局 Audit Event 发布门禁作为 blocker。
3. **跨文档冲突**：`openspec/config.yaml` 仍描述旧 `Handler → Service → Store → Model` 单一路径、`{code,message,...}` 和强制 TDD，而当前 `AGENTS.md`、DDD 规范及用户本次决策已经明确三通道、`{code,msg,...}` 和测试环境临时豁免。
4. **发布目标改变**：目标是 2026-07-27 前部署测试环境，不是生产验收。全局审计提交 `ff44305` 只完成 Integration Log 基础、Access Log 加固和离线覆盖门禁；`integrationlog.Repository` 未装配生产组合根，`cmd/audit-coverage` 不在运行时，现有代码可安全冻结。

### 权威来源与利益相关方

- 用户本次确认决定是审计/测试/里程碑范围的最高优先级。
- 七月标准评审稿是业务冲突裁决来源；冻结 PRD 保留详细不变量、API、状态机和异常闭环；既有 Ticket 保留已评审纵向切片；代码和提交只证明完成状态。
- 利益相关方包括后端、前端、产品、测试环境验收负责人、运维，以及企微、支付、Gateway、运营商与对象存储配置负责人。

### 约束

- 技术栈固定为 Go 1.25.4、Fiber v2、GORM、PostgreSQL、Redis、Asynq、Viper、Zap、sonic、Validator，不新增替代依赖。
- 数据库不使用外键或 GORM 关联标签；金额以分为单位；生命周期状态用 `int`，类型/方式用 `string`。
- API 使用 `{code,msg,data,timestamp}`、`pkg/errors`、后端权限与数据范围、默认 20/最大 100 分页。
- 触碰式迁移以完整用例为单位，禁止顺手重构未触碰旧代码。
- 本 Change 只写 OpenSpec 规划产物；不修改业务代码、不运行测试、不提交 Git。

## Goals / Non-Goals

**Goals:**

- 建立唯一、稳定、可勾选的 28 线总台账和后续唯一实施入口。
- 真实表达后端、前端、验证、发布四个维度，不把代码存在等同验收完成。
- 保留冻结业务规则，将全部未完成工作组织为三批可执行纵向切片，并消除悬空和模糊依赖。
- 在不削弱资金、审批、异步与外部调用可靠性的前提下，形成测试环境快速交付顺序。
- 冻结现有审计代码并将 Audit Event 移出本 Change 及本次实际上线范围，不把它作为测试环境或生产上线阻塞项。
- 统一前后端契约、停机部署、回滚和延期验证边界。

**Non-Goals:**

- 不重写、废弃或回填全部原 PRD/Tickets，也不再创建一批 `.scratch/issues`。
- 不实施任何七月业务代码、迁移、前端页面或运行时配置。
- 不加入需求16，不创建 `distribution` 领域或任何分销/提现能力。
- 不继续开发 Audit Event Writer、审计中心、历史投影、审计导出、保留清理或一次性审计切换。
- 不删除 `ff44305`、`pkg/sanitizer`、`tb_integration_log` 迁移或其他已有可靠性代码。
- 不新增/运行自动化测试，不执行真实外部验收；这些只作为生产前延期项。

## Decisions

### 1. 使用三个总控 capability，而不是复制 28 份业务规格

本 Change 使用 `july-iteration-master-ledger`、`july-iteration-delivery-contract`、`july-iteration-test-release-gate` 三个新能力。业务细节继续引用标准评审稿与冻结 PRD，`tasks.md` 则把每条线落实为具体纵向任务。

**理由**：统一 Change 的职责是建立权威台账、执行依赖和发布契约；完整复制 28 份 PRD 会制造第二套易漂移业务真相。

**否决方案**：为每个 UR 建一个重复 spec。该方案文件数量大、易与冻结 PRD 不一致，也违背“不重写原 PRD”的定位。

### 2. 多维状态替代单一完成状态

每条线记录后端、前端、验证、发布四维状态，并允许“元数据待收口”。初始证据如下：

| 稳定编号 | 初始后端状态 | 前端/验证状态 | 证据结论 |
|---|---|---|---|
| `JULY-TECH-FOUNDATION` | 已完成 | 本仓交付完成 | PRD `completed`、12/12 Tickets、提交 `17782d5`/`7e0171a` |
| `JULY-UR55` | 已完成 | 跨仓状态不可独立证明 | 5/5 Tickets、提交 `9818537` 等；PRD 顶层滞后 |
| `JULY-UR45` | 后端完成 | 前端/人工待确认 | 提交 `55bdc3a`；2 张 Ticket 元数据未收口 |
| `JULY-UR46` | 后端完成 | 前端/人工未完成 | 4/4 `done（后端）`、提交 `8d65b26` 等 |
| `JULY-UR60` | 后端完成 | 前端联调/人工未完成 | 2 completed + 1 ready-for-human |
| `JULY-UR86` | 后端完成 | 前端/历史抽样未完成 | 1 completed + 1 blocked、提交 `c58773e` |
| 其余 22 条 | 未开始 | 未开始 | PRD/Tickets 均未形成业务实现证据 |

**理由**：防止把“代码已存在”“测试曾写过”“Ticket 元数据完成”“测试环境部署”混为同一事实。

**否决方案**：只使用 `[x]/[ ]` 标记整条需求。它无法表达后端完成但前端、人工或生产门禁未完成。

### 3. 按当前 DDD 三通道覆盖旧配置中的单一路径

任务采用：复杂写 `Handler → Application → Domain → Repository/Infrastructure`；简单写 `Handler → Application 事务脚本 → Persistence`；读取 `Handler → Query → GORM/DTO`。旧 `Handler → Service → Store → Model` 只保留给未触碰旧用例。

依赖注入继续使用结构体字段/构造器显式注入 Application、Query、Repository、Adapter、Outbox、Integration Log 与配置；Domain 不依赖 Fiber/GORM/Redis。常量进入 `pkg/constants`，Redis Key 由函数生成。

**理由**：这是当前 `AGENTS.md` 和 DDD 规范的触碰式演进合同，比 `openspec/config.yaml` 的旧上下文更新且更具体。

**否决方案**：强制所有新需求继续堆入旧 Service，或全仓一次性 DDD 重构；前者扩大旧 Service，后者超出当前完整用例边界。

### 4. 审批业务与外部渠道依赖倒置

退款、线下代充等业务的 Domain/Application 使用业务侧定义的 Approval Port，只依赖通用审批实例、标准决策和终态事件。WeCom Adapter 是首个渠道实现，负责 Token、账号绑定、模板/控件映射、附件副本、提交、回调、轮询和恢复，并将企微状态翻译为标准决策。未来接入钉钉或其他渠道时只新增 Adapter 和渠道配置，不修改退款、充值、钱包、佣金或套餐终结规则。

通用审批实例仅保存业务类型/业务 ID、真实提交人、`provider`、`external_ref`、标准状态、请求/决策快照及关联 ID。企微 `sp_no`、模板 ID、控件 ID、userid 绑定和加密回调参数只属于 WeCom Adapter 或渠道专属配置。本地业务附件仍是权威原件，外部审批附件只是副本。系统不建设 BPMN、节点编排、审批人路由或会签/或签等本地通用审批流引擎，这些仍由外部平台负责。

新提交在有效 Adapter 未装配、场景未发布或身份不可解析时，必须在写入业务单、通用审批实例和 Outbox 之前失败关闭。因此业务核心可先于企微实现与构建，但测试环境开放线下代充/退款提交入口前，必须完成 WeCom Adapter 与组合根装配。

**理由**：审批是业务决策边界，企微只是当前交付渠道；依赖倒置既允许业务核心先行，也避免未来替换渠道时重写资金和状态机。

**否决方案**：让退款/充值直接依赖企微 SDK、`sp_no` 或企微状态码；或为了渠道灵活性自建通用审批流引擎。前者锁定供应商，后者扩大了本期范围并重复外部平台能力。

### 5. 三批实施与稳定依赖图

```mermaid
flowchart TD
    PF[JULY-TECH-FOUNDATION 已完成]
    N[B1-01 公共通知]
    A[B1-02 渠道无关审批核心]
    C[B1-03 UR38 信用钱包]
    S[B1-04 UR94 卡状态]
    G[B1-05 UR43 系列授权]
    L[B1-06 UR47 限速]
    P[B1-07 UR48 支付方式]
    O[B1-08 UR96 业务员]
    X[B1-09 UR98 换货继承]
    R40[B2-01 UR40 可售策略]
    R73[B2-02 UR73 复机]
    R53[B2-03 UR53 实名筛选]
    R62[B2-04 UR62 H5 顺序]
    R97[B2-05 UR97 余额预警]
    R36[B2-06 UR36 批量订购]
    R49[B2-07 UR49 设备批量]
    R34[B3-01 UR34 充值业务核心]
    R35[B3-02 UR35 退款业务核心]
    W[B3-03 UR37 WeCom Adapter]
    R57[B3-04 UR57 禁止换货]
    R33[B3-05 UR33 临期]
    R44[B3-06 UR44 摘要]
    R42[B3-07 UR42 导出]
    PF --> N & A & C & S & G & L & P & O & X
    S --> R73 & R53 & R62
    C --> R97 & R36 & R34 & R35
    O --> R97 & R33
    N --> R97 & R34 & R35 & R33
    A --> R34 & R35
    R40 --> R36 & R33
    R36 --> R49
    R34 --> W
    R35 --> W
    A --> W
    W --> R44
    R35 --> R57 & R44
    R34 --> R44
    R33 --> R42
    R44 --> R42
```

UR46 已完成后端并作为 B3-05/B3-07 的已满足后端依赖；UR55 已满足 UR46。UR45、UR46、UR60、UR86 只进入最终前端/人工/元数据收口，不重复实现后端。

**理由**：先交付公共写入、资金和外部系统边界，再交付依赖它们的业务，最后组合复杂业务，可消除原 `.scratch` 的悬空引用。

**否决方案**：按数据库、Service、Handler 水平排期，或让下游先各自复制公共能力；两者都会制造重复实现和不可验证中间态。

### 6. 原 Tickets 保留业务粒度，但统一移除测试与 Audit Event 阻塞

已有 Tickets 的业务切片 SHALL 在对应总任务内逐项映射；原本纯自动化 Harness、验收测试和真实外部门禁移动到“延期验证与生产门禁”，Audit Event 写入、审计中心与治理子项则从本 Change 及本次实际上线范围排除。不存在路径和占位符改为本 Change 的稳定任务号：

- 公共通知 04 改依赖 `B1-08.6`，不再引用不存在的 UR96 文件名。
- UR37-01～13 各自映射为后置 WeCom Adapter 纵向任务，不成为 UR34/UR35 业务核心的编译前置；原 UR37-14“退款首个真实企微门禁”分为测试环境 Adapter 装配检查和生产前 `6.2` 真实验收，不反向阻塞 UR34/UR35 核心规则实现。
- UR48/UR49 发布依赖使用本 Change 任务号，不依赖漂移标题。
- 所有 `.scratch/tech-global-audit/issues/01`、`19`、`20`、`21` 等 Audit Event 阻塞边从测试环境和生产上线依赖图删除；未来如需恢复审计能力，另开独立 Change，不在本 Change 的 `6.*` 清单中恢复。

**理由**：用户已明确授权测试和审计范围调整；保留旧 blocker 会让测试环境目标不可执行。

**否决方案**：修改原 Tickets。原 Tickets 需要保留评审历史，本 Change 只提供新的执行映射。

### 7. 前后端契约以“冻结字段 + 状态矩阵 + 人工验收点”管理

每条涉及 API 的纵向任务记录 Endpoint、请求字段、完整 `data`、用户类型、资源所有权、分页/排序/过滤、错误码、状态/枚举、前端页面与异常状态。响应包络一律为 `{code,msg,data,timestamp}`，参数错误使用 `CodeInvalidParam`，资源不存在/越权使用 `CodeForbidden` 统一语义。

当前仓库无前端源码，因此后端任务只交付 OpenAPI、样例、字段和框架无关交互；前端完成必须由外部仓库或人工证据单独勾选。新增 Handler 同步 `cmd/api/docs.go` 与 `cmd/gendocs/main.go`。

**理由**：可以防止后端代码完成被误记为全链路完成，同时给前端明确实现输入。

### 8. 资金、审批、异步与外部调用保留完整异常闭环

- **资金**：钱包余额/版本/流水是 Domain Ledger；扣款、冻结、入账、退款按唯一业务键、乐观锁/条件更新和同事务事实保证；支付成功与钱包入账分阶段，已收款不得因后续失败丢失。
- **审批**：业务侧先固化申请快照并只消费 `approved/rejected/cancelled/deleted/revoked_after_approved` 标准决策；Adapter 负责外部节点、审批人、意见和附件副本，并将回调/轮询翻译到同一同步用例。提交结果未知不盲重试；通过后撤销按是否已产生资金事实分流。
- **异步**：关键副作用同事务写 Outbox，Relay 投递 Asynq，消费者按至少一次与处理租约设计；任务五态和业务成功/失败计数分离。
- **外部调用**：Integration Log 在请求/回调边界记录脱敏尝试、结果未知和恢复事实；支付、审批渠道、Gateway、运营商状态不得由日志替代业务表。
- **错误**：Application/Domain/Query 使用 `pkg/errors`，客户端不接收底层 SDK/GORM/Validator 错误；关键错误使用中文日志并携带稳定关联 ID。

Audit Event 不在本 Change 及本次实际上线范围内接入新业务，以上 Domain Ledger、Integration Log、Outbox、事务和幂等均不得因此延期。

### 9. 审计冻结对运行时无新增影响

边界保持：Access Log 负责 HTTP 调试；Audit Event 属于本 Change 范围外的操作者治理能力；Domain Ledger 负责金额/状态事实；Integration Log 负责外部交互；Outbox 负责可靠投递。

`ff44305` 的运行时分析为：

- `integrationlog.Repository` 当前仅在自身测试实例化，未注入 API/Worker 生产组合根；冻结不会改变现行业务写路径。
- `cmd/audit-coverage` 扫描仓库并生成离线基线，不属于运行时请求或 Worker。
- `pkg/sanitizer` 已被 Access Log 复用敏感字段判定，递归遍历、路由策略、摘要和 50KB 截断仍由 logger 包执行，必须保留。
- `000167_create_audit_integration_log` 只建独立表与索引，`audit_event_id` 为普通 bigint，无外键，可保留而不要求启用审计中心。

**理由**：保留已提交安全和可靠性能力，同时避免半成品 Audit Event 门禁阻塞业务。

**否决方案**：回滚 `ff44305` 或删除审计迁移；没有必要且会丢失 Access Log 加固和未来恢复基线。

### 10. 测试配置冲突由用户本次里程碑决策覆盖

本测试环境里程碑不生成/运行自动化测试。每个批次只执行 `gofmt`、必要生成、`go build ./...`、迁移/路由/Worker/配置部署检查。状态使用“代码完成、验证延期”，不写“PASS”。

`openspec/config.yaml` 的 TDD、覆盖率与 `{message}` 规则属于通用旧配置；本次用户明确决策、`AGENTS.md` 和本 Change 的 `{msg}` 契约优先。生产前必须重新恢复自动化、真实依赖、性能、安全、权限和人工验收。

**理由**：满足明确交期决定，同时用状态和延期清单控制风险，不伪造证据。

## Risks / Trade-offs

- **[无自动化回归导致状态机、资金与权限缺陷更晚暴露]** → 每批强制构建和部署检查；测试环境限制访问与资金；所有未执行验证进入生产阻塞清单，禁止沿用豁免。
- **[三批范围仍大，2026-07-27 前无法全部完成]** → 依赖 frontier 可并行，但下游只在具体上游完成后启动；状态台账实时反映未开始和代码完成/验证延期，不通过改状态掩盖延期。
- **[原 Tickets 中审计与测试子项被混为同一延期项]** → 在任务映射中区分处理：自动化与真实验收转 `6.*`，Audit Event 明确移出本 Change；原文件保留历史，不改写其评审记录。
- **[Audit Event 未接入导致缺少统一操作者治理证据]** → 保留 Access Log、Domain Ledger、Integration Log 和关联 ID；本次实际上线接受这一治理缺口，未来是否建设由独立 Change 决定。
- **[Integration Log Repository 未生产装配但下游以为已可用]** → 每个真正需要外部交互的业务纵向任务显式完成 Adapter/组合根装配；不能把迁移存在等同运行时接入。
- **[前端仓库不在当前工作区导致后端状态被过度声明]** → 前端契约和人工验收独立复选框，后端无法代勾。
- **[停机迁移后存在不可逆审批/支付/资金事实]** → 开放访问前验证失败可回退；产生事实后暂停生产者、保留流水/Outbox/Integration Log并前向修复，不清表、不恢复旧 Writer。
- **[原 PRD 的依赖环阻塞执行]** → UR33 先交付临期 Query/通知，UR42 后接导出 Scene；UR34/35 先交付状态模型，UR44 再投影摘要，UR42 最后接 Scene。
- **[渠道 Adapter 后置导致业务代码已完成但入口不可用]** → 业务核心以 Port 构建并保持新提交失败关闭；测试环境开放入口必须引用 WeCom Adapter 装配任务，不将“代码完成”记为“可发布”。
- **[旧配置与当前规范继续漂移]** → 本 Change 明确优先级；不在本次顺手修改 `openspec/config.yaml`，另行治理。

## Migration Plan

### 规划到实施

1. 冻结本 Change 的 proposal/design/specs/tasks，后续不从分散 `.scratch` 目录直接启动七月新工作。
2. 按 B1 → B2 → B3 的具体编号领取任务；B1 先固化渠道无关 Approval Port，B3 先完成 UR34/UR35 业务核心，再实现 WeCom Adapter 和组合根装配；同批无依赖项可并行，有依赖项顺序执行。
3. 每个需求先完成冻结 PRD 的业务纵向切片，再执行该批 `gofmt`、必要生成、`go build ./...` 和部署检查。
4. 完成 F1 已落地需求的元数据/前端/人工收口，再执行 F2 测试环境装配与停机部署。
5. 测试环境运行期间保留 D 组延期项未勾选；生产发布另开恢复窗口逐项完成。

### 测试环境停机发布顺序

```mermaid
flowchart LR
    Freeze[冻结版本与配置] --> Stop[维护模式/停止相关写入和 Worker]
    Stop --> Migrate[执行增量迁移与前置数据检查]
    Migrate --> Backend[发布 API、Relay、Worker]
    Backend --> Frontend[发布匹配的前端版本]
    Frontend --> Configure[装配企微/支付/Gateway/运营商/对象存储配置]
    Configure --> Check[构建、路由、Worker、迁移、版本一致性部署检查]
    Check --> Resume[恢复 Worker 与访问]
```

### 回滚

- 开放访问前：可回滚应用和确认可逆的迁移；未通过检查时保持维护模式。
- 开放访问后：已产生的审批、支付、钱包流水、订单、退款、充值、通知、Outbox、Integration Log 与部分成功批量任务不得删除；暂停异常入口并前向修复。
- 支付成功未入账、审批终态未处理、Outbox 积压必须由恢复 Worker 幂等完成，不能要求用户重复提交或重复付款。
- 信用额度一旦产生负余额，不得回退到忽略信用边界的旧扣款逻辑。

### 生产发布前门禁

- 自动化测试与完整构建、真实 PostgreSQL/Redis/Asynq 验证。
- 真实企微模板/绑定/附件/回调/轮询，微信/支付宝预下单/查单/回调，Gateway 限速与运营商回调验收。
- 前后端全链路、历史数据抽样、存量迁移和停机演练。
- 权限、分页、N+1、性能、安全、Access Log 敏感矩阵与回滚演练。
- Audit Event Writer、审计中心和历史投影不属于本 Change 的生产门禁；未来如需建设，另开独立 Change，不反向阻塞本次上线。

## Open Questions

无阻塞性业务问题。实现期仍需由部署负责人提供企微、支付、Gateway、运营商、对象存储和前端仓库的测试环境配置与版本，但这些属于执行输入，不改变本 Change 的范围或架构决定。
