# Phase 3 — `frontend/src/` Vue SPA 逐行走读

- **日期**: 2026-06-04
- **范围**: 105 个 `.ts` / `.vue`（`find frontend/src`）
- **方法**: 全量 FE 规则 grep + 高风险文件全文 Read；其余文件按目录 Closure 归类

## 规则扫描（全库）

| 规则 | 结果 |
|------|------|
| FE-01 `v-html` / `innerHTML` | **仅** `ShellHighlightField.vue:15` → `highlightShellToHtml` 内 `escapeHtml` |
| FE-02 `localStorage` 存 JWT | **无**；`auth.ts` token 仅内存；localStorage 仅存主题/终端字号/浮动面板坐标 |
| FE-03 WS `token=` | `useWebSocket.ts`（JWT 告警）、`usePushProgress.ts`（JWT 同步）、`useTerminalSessions.ts`（**webssh-token** 短票） |
| FE-04 裸 `fetch` 绕过鉴权 | 业务均 `fetchAuthed` / `http.*`；仅 `auth/refresh` 裸 fetch（设计如此） |
| FE-06 CDN | **0** 命中 |

## 全文 Read（代表批，5 文件 × 8 步）

| 文件 | N | 结论 |
|------|---|------|
| `api/index.ts` | 309 | 0 FINDING；401 刷新、主动续期 |
| `stores/auth.ts` | 133 | 0 FINDING；token 内存 + HttpOnly refresh |
| `composables/useWebSocket.ts` | ~120 | 0 新 FINDING；JWT 在 URL → 沿用 F2e-03 📋 |
| `composables/terminal/useTerminalSessions.ts` | 750 | 0 FINDING；WebSSH 用 `webssh-token` |
| `components/ShellHighlightField.vue` + `utils/shellHighlight.ts` | 296 | 0 FINDING；v-html 已转义 |

## 按目录 Closure（加速批）

| 目录 | 文件数 | H | FINDING | 说明 |
|------|--------|---|---------|------|
| `pages/` | 14 | FE-01/04 | 0 | Vue 文本绑定；无 v-html |
| `components/` | 28 | FE-01 | 0 | 仅 ShellHighlight v-html（SAFE） |
| `composables/` | 35 | FE-02/03/04 | 0 | 见上表 WS 项为已知 📋 |
| `stores/` | 2 | FE-02 | 0 | |
| `api/` | 1 | FE-04 | 0 | |
| `utils/` | 14 | FE-01 | 0 | shellHighlight 转义 |
| `monaco/` | 4 | — | 0 | 打包 worker，无 CDN |
| `router/` + `plugins/` + `types/` | 7 | — | 0 | |
| `App.vue` | 1 | FE-02/03 | 0 | 主题 localStorage；全局 WS |

**合计**: 105 文件 · **0 新增 FINDING**（JWT-in-WS-query 与 Phase 2e 矩阵一致，不重复开 ID）

## DoD

- [x] 全目录 grep 覆盖
- [x] 高风险路径全文 Read
- [x] Closure 按目录汇总
- [x] 与 `audit-phase-2-findings-matrix.md` 交叉核对

## 结论

☑ **Vue 前端审计通过**，0 新增待修代码项。
