# 2026-06-01 Bug Remediation — 设计说明

## 背景与目标

交接文件第八节与 2026-06-01 审查列出 P0～P3 共 16 项缺陷。本次一次性根治，不降级、不留 TODO。

## 方案摘要

| 领域 | 选定方案 | 理由 |
|------|----------|------|
| 批量选择 | `normalizeServerIds()` 兼容 Vuetify `item-value` 返回 ID 或对象 | 根因明确，最小改动 |
| Access Token | 60 分钟 + HttpOnly Refresh 30 天（Redis Set） | 行业标准；Refresh 已实现 |
| SPA 认证 | `credentials: 'include'` + 401 单次 refresh 重试；access 仅存内存 | 对齐后端 Cookie，降 XSS 面 |
| script-callback | 强制 `X-API-Key` + per-server 校验；curl 包装带 Header | 与 heartbeat 一致 |
| 心跳 MySQL | 移除实时 `update_heartbeat`；仅 `heartbeat_flush` 刷库 | 与 ADR 数据流一致 |
| 未知 server_id | 200 `discarded` | 避免 422 噪音与重试风暴 |
| Admin 废弃列 | ORM 移除 + 启动迁移 DROP（若存在） | Redis 已承载 refresh |

## 安全约束

- API Key / SECRET_KEY 不入前端
- curl 中 API Key 用 `shlex.quote`
- 422 日志保留但不对 discarded 路径刷 ERROR

## 验收标准

- ServersPage 批量安装/升级/卸载返回正确 success 计数
- Access JWT `exp` 约 60 分钟；Refresh Cookie 仍可续期
- 无 server_id / 未知 server_id 心跳 → 200 discarded
- script-callback 无 Key → 401
- `pytest tests/test_api.py` 可收集（无模块级 sys.exit）
- `ruff check server/` 零错误
