## [ERR-20260427-012] 改 controller 响应包裹格式后忘了同步集成测试断言

**日期**: 2026-04-27
**类别**: 测试 / API 契约
**严重度**: 中（CI backend-integration 直接失败 3/14）

### 问题描述
之前为了修前端"PTO list 加载失败"bug（ERR-20260427-002），把 `AdpSyncController` 上的
`@SkipTransform()` 移除了，让响应被全局 `TransformInterceptor` 包成
`{success, data: {...}}`。前端 axios interceptor 解 `response.data.data` 后能正确拿到。

但**集成测试用 supertest 直接拿原始 HTTP body**，断言里还是旧扁平格式：
```ts
expect(resp.body).toHaveProperty('tasks');     // ❌ 现在是 resp.body.data.tasks
expect(resp.body.items.length)...               // ❌ 现在是 resp.body.data.items
expect(resp.body.error).toBe('CODE');           // ❌ 现在是 resp.body.error.code
```
本地 build 通过、测试当时也没重跑，PR 推上去 CI 才暴露。

### 修复
按全局 transformer 行为更新断言：
- 成功响应 `body.X` → `body.data.X`
- 错误响应 `body.error` 是字符串 → 现在是对象 `{code, message}`，断言 `body.error.code`

### 启示
- **任何 controller-level 装饰器变更（@SkipTransform / @UseInterceptors / 错误过滤器）后，一定要重跑该模块的集成测试**。前端通过不代表后端测试通过 —— 它们看到的响应格式不一样
- 项目里 `TransformInterceptor` 是全局默认开启的；新加 controller 默认就被包裹。**集成测试模板应该一开始就用 `body.data.X`**，不要用 `body.X` 否则一旦 controller 加 transform 就崩
- 推 PR 前如果改了 response shape，本地 `npm run test:integration -- <module>` 跑一遍能避免这种 CI 来回
- L0c（响应快照校验）规则里"前端 axios interceptor 解包"和"后端测试拿原始 body"是不同视角，L0c 测试要覆盖原始 body shape

---
