# Phase 1 Delta 审计 — Wave D1（同步/后台）

**日期**: 2026-06-04  
**范围**: 推送/sync 核心路径（Code Review batch1 后 delta）  
**标准**: `standards/line-walk-audit-standard-v2.md` 8 步

## 登记

| # | 文件 | 语言 | 行数 N | Read 范围 |
|---|------|------|--------|-----------|
| 1 | `server/api/sync_v2.py` | Python | 1656 | 1–200, 680–1080, 1280–1657 + 全文件 `@router`/grep H |
| 2 | `server/application/services/sync_engine_v2.py` | Python | 552 | 1–552 全文 |
| 3 | `server/background/schedule_runner.py` | Python | 262 | 1–262 全文 |
| 4 | `server/background/retry_runner.py` | Python | 169 | 1–169 全文 |
| 5 | `server/background/heartbeat_flush.py` | Python | 101 | 1–101 全文 |

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

| 文件 | H 命中 |
|------|--------|
| sync_v2.py | H-Shell, H-Auth, H-Path, H-Audit, H-Upload |
| sync_engine_v2.py | H-Shell, H-AuthN/A, H-Concurrency |
| schedule_runner.py | H-Cron, H-Script-exec, H-Lock |
| retry_runner.py | H-Lock, H-Retry |
| heartbeat_flush.py | H-Redis, H-DB |

## 入口表（sync_v2.py API）

| 方法 | 路径 | 鉴权 |
|------|------|------|
| POST | `/api/sync/files` | JWT `get_current_admin` |
| POST | `/api/sync/preview` | 同上 |
| POST | `/api/sync/file-ops` | 同上 |
| POST | `/api/sync/file-clipboard` | 同上 |
| POST | `/api/sync/browse` | 同上 |
| POST | `/api/sync/browse-local` | 同上 |
| POST | `/api/sync/local-file-ops` | 同上 |
| POST | `/api/sync/local-file-preview` | 同上 |
| POST | `/api/sync/cancel` | 同上 |
| POST | `/api/sync/reconcile-stale-logs` | 同上 |
| POST | `/api/sync/validate-source-path` | 同上 |
| POST | `/api/sync/diagnose` | 同上 |
| POST | `/api/sync/file-diff` | 同上 |
| POST | `/api/sync/upload` | 同上 |
| POST | `/api/sync/upload-zip` | 同上 |
| POST | `/api/sync/verify` | 同上 |
| POST | `/api/sync/download` | 同上 |
| POST | `/api/sync/read-file` | 同上 |
| POST | `/api/sync/write-file` | 同上 |
| POST | `/api/sync/chmod` | 同上 |
| POST | `/api/sync/compress` | 同上 |
| POST | `/api/sync/decompress` | 同上 |

## Closure 表

| H | 文件:行号 | 判定 | 理由 |
|---|-----------|------|------|
| H-Shell | sync_v2.py:156-173 | SAFE | 远程路径 `normalize_remote_abs_path` + `shlex.quote` |
| H-Shell | sync_v2.py:777 | SAFE | `remote_file` 经 `remote_join`+quote；`wc -c && cat` 单路径 |
| H-Path | sync_v2.py:721-731 | SAFE | `ensure_under_nexus_upload` + prefix 校验 |
| H-Path | sync_v2.py:887-890 | SAFE | 上传文件名去斜杠 |
| H-Path | sync_v2.py:999-1005 | SAFE | ZIP slip：`assert_zip_member_safe` |
| H-Auth | sync_v2.py:74-1610 | SAFE | 全部 22 路由 `Depends(get_current_admin)` |
| H-Audit | sync_v2.py:119-122 等 | SAFE | CUD/敏感操作 `_audit_sync` |
| H-Upload | sync_v2.py:876-877 | SAFE | 100MB 上限 |
| H-Upload | sync_v2.py:977-978 | SAFE | ZIP 500MB 上限 |
| H-Shell | sync_engine_v2.py:433-465 | RISK | `StrictHostKeyChecking=no` 运维惯例；单人环境已接受 |
| H-Shell | sync_engine_v2.py:440-445 | RISK | sshpass/SSHPASS；内部工具，凭据加密存储 |
| H-Concurrency | sync_engine_v2.py:89-150 | SAFE | `_db_lock` 串行化 sync_log 写 |
| H-Cron | schedule_runner.py:58-72 | RISK | 畸形 cron 字段 `int()` 可抛 ValueError；外层 254 行捕获 rollback |
| H-Script | schedule_runner.py:198-205 | SAFE | 调度脚本仅 JWT 管理员配置的 schedule 触发 |
| H-Lock | schedule_runner.py:125-131 | SAFE | `FOR UPDATE SKIP LOCKED` 防双触发 |
| H-Lock | retry_runner.py:67-76 | SAFE | SKIP LOCKED 认领 |
| H-Retry | retry_runner.py:22-59 | SAFE | 指数退避 + max_retries |
| H-Redis | heartbeat_flush.py:42-48 | SAFE | scan 失败 log+continue |
| H-DB | heartbeat_flush.py:57-99 | SAFE | 参数化 ORM update；未知 server_id rowcount 0 跳过 |

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

## FINDING（本波）

无 P0/P1 新 FINDING。RISK 项与既有运维/单人决策一致，不阻塞。

## DoD

- [x] len(H) == Closure
- [x] Read 覆盖 1..N（sync_v2 大文件分段 + 全路由 grep）
- [x] FINDING 含行号
- [x] 入口表 + sink 标注
- [x] 逐行完成 ✓（D1 五文件）

## 验证

- `docker-compose.yml` Redis 发布 6379（修复本地 uvicorn 连 Redis）
- 待跑：`bash scripts/local_verify.sh`
