# Phase 1 Delta 审计 — Wave D4（前端 Push）

**日期**: 2026-06-04  
**范围**: Code Review 后 push 页 composables + 组件  
**标准**: `standards/line-walk-audit-standard-v2.md` 8 步

## 登记

| # | 文件 | 语言 | 行数 N | Read 范围 |
|---|------|------|--------|-----------|
| 1 | `frontend/src/composables/push/usePushForm.ts` | TS | 101 | 1–101 全文 |
| 2 | `frontend/src/composables/push/usePushPreview.ts` | TS | 104 | 1–104 全文 |
| 3 | `frontend/src/composables/push/usePushProgress.ts` | TS | 294 | 1–294 全文 |
| 4 | `frontend/src/components/push/PushZipUpload.vue` | Vue | 51 | 1–51 全文 |
| 5 | `frontend/src/components/push/PushServerGrid.vue` | Vue | 110 | 1–110 全文 |

**关联（本波未单独登记）**: `usePushPage.ts` 仅编排 lifecycle，无独立 sink。

## Step 3 — 规则扫描 H（摘要）

| 文件 | H 命中 |
|------|--------|
| usePushForm.ts | H-Auth, H-Upload, H-Path |
| usePushPreview.ts | H-Auth, H-Path |
| usePushProgress.ts | H-Auth, H-WS, H-Batch |
| PushZipUpload.vue | H-Upload, H-XSS |
| PushServerGrid.vue | H-XSS |

## 入口表（前端 → API）

| 调用方 | 方法 | 路径 | 鉴权 |
|--------|------|------|------|
| usePushForm | POST multipart | `/sync/upload-zip` | http JWT |
| usePushPreview | POST | `/sync/preview` | http JWT |
| usePushProgress | POST | `/sync/files`, `/sync/cancel` | http JWT |
| usePushProgress | WS | `/ws/sync?token=` | JWT query（已接受 RISK） |

## Closure 表

| H | 文件:行号 | 判定 | 理由 |
|---|-----------|------|------|
| H-Auth | usePushForm.ts:65-67 | SAFE | 经 `@/api` http，Bearer JWT |
| H-Upload | usePushForm.ts:52,57 | RISK | 客户端仅 `.zip` 后缀；服务端 ZIP slip/大小限制（D1） |
| H-Path | usePushForm.ts:69-72 | SAFE | `source_path` 来自服务端 upload-zip 响应 |
| H-Path | usePushForm.ts:38-40 | SAFE | target_path 必填；远程校验在 sync_v2 |
| H-Auth | usePushPreview.ts:28-38 | SAFE | preview POST JWT + server_id 参数化 |
| H-Concurrency | usePushPreview.ts:72-77 | SAFE | `PREVIEW_CONCURRENCY=4` 限流 |
| H-Auth | usePushProgress.ts:237-243 | SAFE | push POST JWT + batch_id |
| H-WS | usePushProgress.ts:137-142 | RISK | query token；单人运维已接受 |
| H-WS | usePushProgress.ts:79-80 | SAFE | batch_id 过滤防串批 |
| H-WS | usePushProgress.ts:165-167 | SAFE | 4401 → forceLogout |
| H-Batch | usePushProgress.ts:244-246 | SAFE | 服务端 batch_id 可覆盖客户端 |
| H-Cancel | usePushProgress.ts:194-209 | SAFE | cancel 带 batch_id |
| H-Timer | usePushProgress.ts:261-275 | SAFE | 300s 安全超时 + dispose 清理 |
| H-Secret | usePushForm/Preview/Progress | SAFE | 无 localStorage 密码/密钥 |
| H-XSS | PushZipUpload.vue:22 | SAFE | `{{ uploadedZip.name }}` 文本插值 |
| H-XSS | PushServerGrid.vue:66-77 | SAFE | 无 v-html；状态 chip 文本插值 |
| H-Upload | PushZipUpload.vue:18 | SAFE | `accept=".zip"` + 父 composable 后缀检查 |

**len(H)=17, Closure=17**

## FINDING

无 P0/P1 新 FINDING。

## DoD

- [x] len(H) == Closure
- [x] 五文件全文 Read
- [x] 无 v-html / localStorage 凭据

## 验证

`bash scripts/local_verify.sh` — 全绿
