Smail/docs/配置系统重构实施任务清单.md
smail f60d3b0880
Some checks are pending
Security Checks / security (push) Waiting to run
整理前后端与测试构建目录并完善配置和安全引导
统一 frontend、backend、test、test-log 和 out 目录,更新构建、部署及测试入口;纳入配置管理兼容与首次安全引导修复;排除本机配置、密钥和测试产物。
2026-09-05 19:19:52 +08:00

1341 lines
114 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Smail 配置系统重构实施任务清单
## 1. 文档信息
| 项目 | 内容 |
|---|---|
| 文档名称 | Smail 配置系统重构实施任务清单 |
| 文档状态 | 待执行 |
| 当前版本 | 0.5 |
| 编写日期 | 2026-08-25 |
| 需求依据 | `docs/配置系统重构需求文档.md` 0.7、`docs/超级管理员重置与邮箱验证码需求文档.md` 0.3 |
| 技术依据 | `docs/配置系统重构技术设计.md` 0.5 |
| 详细子任务 | `docs/超级管理员重置与邮箱验证码实施任务清单.md` 0.3 |
| 适用目录 | `server`、`frontend`、`plugins`、`docs` |
本文档用于按任务点实施、测试、复审和标记配置系统重构进度。除文档任务外,所有编码任务初始状态均为“未开始”;不得因为已有相似代码就直接标记为“已完成”。
---
## 2. 状态和执行规则
### 2.1 状态枚举
| 状态 | 含义 |
|---|---|
| 未开始 | 尚未进入实施 |
| 进行中 | 正在编码或验证 |
| 待复审 | 实施和自测完成,等待独立安全复审 |
| 已完成 | 验收条件全部满足并留存证据 |
| 阻塞 | 存在明确外部依赖,无法继续 |
### 2.2 优先级
| 优先级 | 含义 |
|---|---|
| P0 | 安全边界或后续任务前置条件,必须优先完成 |
| P1 | 核心功能,阻塞阶段验收 |
| P2 | 完整性、体验或运维增强 |
### 2.3 标记规则
任务从“未开始”变更为“已完成”前,必须同时满足:
1. 实施步骤全部完成;
2. 安全要求全部通过;
3. 自动化测试通过;
4. 需要页面验证的任务完成真实浏览器验证;
5. 任务证据填写命令、结果和关键文件;
6. 不存在未说明的失败测试或平台缺口;
7. 经过复审后由“待复审”改为“已完成”。
### 2.4 全局限制
1. 不使用 Docker;
2. 不将真实密码、Token、DSN 或密钥写入仓库和测试日志;
3. 不引入旧弱算法或验证失败后的旧算法回退;
4. 不允许插件读取主配置、临时构造的数据库 DSN、数据库配置或访问主数据库;
5. 不允许仅通过前端隐藏按钮实现权限控制;
6. 不删除旧文件、旧数据库列或旧接口,除非另行获得用户明确许可;
7. 修改源代码后执行格式化、单元测试、集成测试和安全测试;
8. 文档、注释、说明和界面文字使用中文,代码标识符使用简洁英文;
9. 文本文件保持 UTF-8 无 BOM;
10. 提交和推送不属于本清单默认动作,需要用户另行指示。
### 2.5 跨文档依赖与任务归属
本清单使用 `CG-001`~`CG-057` 管理配置系统重构总体任务;`docs/超级管理员重置与邮箱验证码实施任务清单.md` 使用 `AD-001`~`AD-066` 管理超级管理员部署端重置和完整邮箱验证码的详细任务。两份清单共同构成本轮正式开发范围,执行规则如下:
1. “基础”任务先完成通用模型、授权、配置或认证能力,对应 AD 任务才能开始;
2. “聚合”任务必须等待对应 AD 详细任务完成并具备验收证据后才能标记完成;
3. 同一依赖关系只能单向表达,禁止建立 `CG → AD → 同一 CG` 的循环依赖;
4. 状态记录、测试报告和验收证据必须使用完整 `CG-*` 或 `AD-*` 编号;
5. 两份清单发生冲突时,以已确认需求文档和技术设计为准,先修正文档再实施。
| CG 任务 | 关系 | AD 详细任务 |
|---|---|---|
| CG-001 需求和技术设计评审 | 聚合 | AD-001、AD-002 产品决定与权限矩阵 |
| CG-022 SMTP 和邮箱策略 | 基础 | AD-032~AD-038 SMTP、限流、运营数据和定期清理 |
| CG-027~CG-029 统一认证与密码服务 | 基础 | AD-016~AD-021、AD-039~AD-047、AD-050~AD-051 |
| CG-030 分角色跨用户密码重置 | 聚合 | AD-021 |
| CG-031 部署端重置通道 | 聚合 | AD-006~AD-020、AD-062~AD-063 |
| CG-032 通用账户恢复迁移基础 | 基础 | AD-022~AD-025、AD-035~AD-037 |
| CG-038~CG-039 恢复状态机和安全策略 | 基础 | AD-043~AD-047、AD-050、AD-053 |
| CG-040~CG-045 API、页面和浏览器验收 | 聚合 | AD-048~AD-059、AD-064 |
| CG-048 V1 路由和通用请求守卫 | 基础 | AD-048~AD-051 |
| CG-051 平台部署验证 | 聚合 | AD-011、AD-015 |
| CG-052 完整自动化回归 | 聚合 | AD-060~AD-064 |
| CG-057 最终验收 | 聚合 | AD-066 |
---
## 3. 总体进度
| 阶段 | 任务范围 | 状态 | 完成数/总数 |
|---|---|---|---:|
| 第一阶段 | 需求、安全边界和迁移基线 | 进行中 | 3/4 |
| 第二阶段 | 统一配置管理器 | 未开始 | 0/9 |
| 第三阶段 | SSL、插件、SMTP 和邮箱分区 | 进行中 | 6/9 |
| 第四阶段 | 三级角色、数据库迁移和统一认证 | 未开始 | 0/9 |
| 第五阶段 | 密保、离线恢复码和 WebAuthn | 未开始 | 0/8 |
| 第六阶段 | 管理页面和账户安全页面 | 未开始 | 0/6 |
| 第七阶段 | 初始化、兼容切换和部署验证 | 未开始 | 0/6 |
| 第八阶段 | 完整安全复审和验收 | 未开始 | 0/6 |
| **合计** | | **进行中** | **3/57** |
---
## 4. 第一阶段:需求、安全边界和迁移基线
### CG-001 完成需求和技术设计评审
- **状态**:已完成
- **优先级**:P0
- **依赖**:AD-001、AD-002
- **设计映射**:技术设计第 31 章
- **修改范围**:`docs/配置系统重构需求文档.md`、`docs/配置系统重构技术设计.md`
- **实施步骤**:复审已确认产品决定;记录评审人和日期;修订冲突描述;确认产品待确认项已经全部关闭;冻结首轮范围和最终验收阻塞边界。
- **安全要求**:不得通过“后续再处理”方式放宽角色、Secret、恢复流程和插件隔离边界。
- **测试要求**:检查配置需求 0.7、独立需求 0.3、技术设计 0.5、CG 清单 0.5 和 AD 清单 0.3 术语一致;确认完整邮箱验证码范围、部署端正式入口和密码重置权限矩阵均有明确结论。
- **验收标准**:两份需求、技术设计和两份任务清单通过文档复审;正式开发范围、角色权限、跨文档依赖和最终验收阻塞条件清晰。
- **回退方式**:仅回退文档版本,不影响代码和配置。
- **验收证据**:2026-08-25 完成五份文档一致性复审;AD-001、AD-002 已冻结正式入口和权限矩阵。
### CG-002 建立敏感字段和安全能力清单
- **状态**:`[x] 已完成,等待复审`
- **优先级**:P0
- **依赖**:CG-001
- **设计映射**:第 3、13、28 章
- **修改范围**:`backend/services/access`、`backend/config`、相关测试和安全文档
- **实施步骤**:列出所有 Secret 字段;定义三级角色能力;定义高风险操作和二次确认要求;允许能力策略声明 `requiresRecoveryCode`;建立 API 到能力映射。
- **安全要求**:能力必须默认拒绝;敏感字段不允许通过通用反射自动输出;`requiresRecoveryCode` 只检查管理员和普通用户,超级管理员明确豁免;角色变更必须按照变更后的目标角色检查目标用户是否需要有效恢复码。
- **测试要求**:为每个管理 API 建立最少一条允许和一条拒绝用例;覆盖管理员和普通用户缺少有效恢复码、超级管理员豁免、角色变更目标用户缺少恢复码及稳定错误码 `RECOVERY_CODE_REQUIRED`。
- **验收标准**:不存在未归类的管理接口、Secret 字段或高风险操作。
- **回退方式**:保留清单和测试,不切换授权读路径。
- **验收证据**:已建立 30 项以上敏感字段目录及 `encrypted_only`、`reference_only`、`memory_only`、`hashed_only` 四类持久化策略;已补齐 18 项管理 API 能力目录,配置更新 `PUT /api/v1/config/:section` 映射到全局配置写能力,配置备份 `GET /api/v1/config/backups` 映射到配置回滚能力;已验证默认拒绝、超级管理员恢复码豁免、管理员和普通用户恢复码要求、目标角色恢复码校验及稳定错误码 `RECOVERY_CODE_REQUIRED`;定向测试、全量测试、`go vet ./...` 和 `git diff --check` 通过。真实平台、多数据库、生产日志观测和最终发布验收仍未完成。
### CG-003 引入显式数据库迁移框架
- **状态**:`[x] 已完成,等待复审`
- **优先级**:P0
- **依赖**:CG-001
- **设计映射**:第 11.4、24.1 章
- **修改范围**:`backend/db`、新增迁移目录和测试
- **实施步骤**:创建 `schema_migration`;实现迁移发现、校验和、数据库锁、事务执行和版本检查;限制生产环境继续依赖无版本 `Sync2`。
- **安全要求**:检测迁移文件篡改;并发启动只能有一个迁移执行者;失败时停止业务服务。
- **测试要求**:MySQL、PostgreSQL、SQLite 的首次迁移、重复执行、校验和冲突和中途失败测试。
- **验收标准**:数据库版本可查询;重复启动不重复执行;失败不会形成半完成结构。
- **回退方式**:保留旧 `Sync2` 兼容开关,但生产默认不使用;不删除现有表。
- **验收证据**:已实现 `schema_migration` 表、迁移版本和名称校验、SHA-256 校验和、SQLite `BEGIN IMMEDIATE` 锁、MySQL `GET_LOCK`、PostgreSQL advisory lock、事务执行、失败回滚、重复执行跳过和版本查询;生产环境默认拒绝无版本 `Sync2`,仅保留显式开发或测试兼容开关。SQLite 首次迁移、重复迁移、并发执行、校验和冲突、未知版本、方言缺失和失败回滚测试通过;MySQL/PostgreSQL 集成测试已建立,当前因未配置 `SMAIL_TEST_MYSQL_DSN` 和 `SMAIL_TEST_POSTGRES_DSN` 而跳过,不能视为真实数据库验收通过。
### CG-004 建立配置重构测试基线
- **状态**:`[x] 已完成,等待复审`
- **优先级**:P0
- **依赖**:CG-001
- **设计映射**:第 29 章
- **修改范围**:`server` 测试目录、`frontend` 测试配置、`docs`
- **实施步骤**:记录当前 Go 和前端测试结果;建立新增测试分类;定义跨数据库和跨平台验证命令;准备无真实凭据的测试配置。
- **安全要求**:测试夹具不得包含真实密钥;失败日志不得打印 Secret。
- **测试要求**:运行当前完整测试并记录既有失败,避免把历史失败误归因于重构。
- **验收标准**:形成可重复的基线命令和脱敏结果,明确未验证项。
- **回退方式**:仅移除新增测试配置,不改变生产代码。
- **验收证据**:已新增 `docs/配置系统重构测试基线.md`,记录 Windows PowerShell 下的 Go 全量测试、迁移专项、`go vet` 和前端构建命令,建立单元、迁移、数据库集成、静态检查、前端构建、安全回归、浏览器和跨平台测试分类;已明确 MySQL/PostgreSQL DSN 仅通过临时环境变量注入,未配置时记录为未验证;已记录 Ubuntu 22.04/24.04、Windows 生产服务、真实 SMTP、多实例和生产观测等外部验收边界。2026-08-27 执行的 `go test ./... -count=1`、`go vet ./...`、迁移专项测试和 `yarn.cmd build` 通过,未使用真实密钥或生产数据库。
### 第一阶段验收
- [x] 需求范围已确认;
- [x] 技术设计已评审;
- [x] 敏感字段和能力清单完整;
- [x] 显式数据库迁移框架可用;
- [x] 当前测试基线已记录。
---
## 5. 第二阶段:统一配置管理器
### CG-005 建立配置模型和固定分区映射
- **状态**:`[x] 已完成,等待复审`
- **优先级**:P0
- **依赖**:CG-001
- **设计映射**:第 6 章
- **修改范围**:`backend/config/model.go`、`root.go`、`smtp.go`、`email.go`、`ssl.go`、`plugins.go`
- **实施步骤**:定义 `RootConfig`、四个分区模型、`SectionRef`、`SectionMeta`、`SetupState`、固定文件名映射和 MySQL、PostgreSQL、SQLite 结构化数据库模型;MySQL/PostgreSQL 使用主机、端口、用户名、加密密码和数据库名称,SQLite 使用后端生成的 `localRef`。
- **安全要求**:API 和配置内容不能覆盖分区实际路径;枚举使用白名单;DSN 只允许连接工厂在内存临时构造,不进入配置、API、日志和审计。
- **测试要求**:模型序列化、三种数据库条件字段、默认端口、非法枚举、任意 SQLite 路径拒绝和固定路径测试。
- **验收标准**:模型能表达需求文档字段且不继续增加旧聚合 `Config` 字段。
- **回退方式**:新模型暂不接入启动流程。
- **验收证据**:
1. `backend/config/model.go` 已建立 `DatabaseType` 白名单,支持 `mysql`、`postgresql`、`sqlite`;MySQL 和 PostgreSQL 在端口为空时分别补充 `3306`、`5432`,SQLite 不生成网络默认端口。
2. `DatabaseConfig` 已按数据库类型表达条件字段:MySQL/PostgreSQL 使用主机、端口、用户名、加密密码和数据库名称;SQLite 仅使用后端引用格式的 `localRef`,并拒绝绝对路径、Windows 路径、UNC 路径、目录分隔符、上级目录、网络字段和密码字段。
3. `backend/config/sections.go` 已固定分区到 `config.json`、`smtp.json`、`email.json`、`ssl.json`、`plugins.json`,并通过 `SectionRef`、`SectionMeta`、代次和 SHA-256 摘要校验阻止任意路径映射;`backend/config/sections_test.go` 覆盖固定文件名、未知分区、路径篡改、Schema、代次和摘要异常。
4. `backend/config/model_database_test.go` 覆盖三种数据库条件字段、默认端口、非法及旧 PostgreSQL 枚举、SQLite 任意路径拒绝和 `localRef` JSON 序列化;`go test ./config -count=1` 通过。
5. 全量验证:在 `server` 目录执行 `go test ./... -count=1`、`go vet ./...` 均通过;`git diff --check` 未发现空白错误。MySQL/PostgreSQL 真实数据库连接、跨平台部署和启动流程仍未在本机完成集成验收,不能据此视为生产验收通过。
### CG-006 实现严格 JSON 解析器
- **状态**:`[x] 已完成,等待复审`
- **优先级**:P0
- **依赖**:CG-005
- **设计映射**:第 8.2 章
- **修改范围**:`backend/config/parser.go`、测试
- **实施步骤**:限制大小和深度;拒绝未知字段、重复键、BOM、无效 UTF-8、尾随内容和范围溢出。
- **安全要求**:错误不得回显 Secret 值和绝对路径。
- **测试要求**:覆盖嵌套重复键、大小写相近字段、超大数值、多个 JSON 值和畸形输入。
- **验收标准**:全部恶意配置夹具被稳定拒绝,正常配置无兼容性回退。
- **回退方式**:保留旧解析器但不在生产开关中启用新路径。
- **验收证据**:`backend/config/parser.go` 已实现配置大小限制、最大嵌套深度、Token 级重复键检测、`DisallowUnknownFields`、BOM 拒绝、无效 UTF-8 拒绝、尾随 JSON 内容拒绝、`UseNumber` 数值解析和精确字段形状校验;超大数值、大小写相近字段、嵌套未知字段、控制字符、畸形输入均使用固定错误,不回显 Secret 或绝对路径。`backend/config/parser_test.go`、`backend/config/parser_security_test.go` 覆盖重复键、嵌套重复键、未知字段、数值溢出、多个 JSON 值、深度和大小限制,以及错误信息脱敏;`go test ./config -count=1` 已通过。
### CG-007 实现配置验证器
- **状态**:已完成,等待复审
- **优先级**:P0
- **依赖**:CG-005、CG-006
- **设计映射**:第 8.3、8.4 章
- **修改范围**:`backend/config/validator.go`、`backend/utils/validation`、测试
- **实施步骤**:实现结构、本地语义、跨分区、路径、域名、端口和插件 ID 校验;将外部连接测试与保存校验分离。
- **安全要求**:保存配置不得隐式连接任意用户输入目标;路径必须限制在受控目录。
- **测试要求**:端口冲突、路径逃逸、域名冲突、插件能力越权和状态机条件测试。
- **验收标准**:无效候选配置不能进入磁盘事务或运行时快照。
- **回退方式**:关闭新配置更新入口,不绕过验证器保存。
- **验收证据**:`backend/config/validator.go` 已实现日志级别、HTTP/HTTPS 端口、SMTP Relay 主机/端口/发件域/加密模式、邮箱端口和登录验证策略、SSL 受控相对路径及证书私钥成对引用、插件逻辑 ID/文件名/网络白名单/凭据格式校验;远程 SMTP 明文 Relay、路径逃逸、绝对路径、非法域名、重复插件网络目标和不安全插件网络目标均被拒绝。`backend/config/runtime_validator.go` 已实现分区元数据、代次、域名唯一性、端口冲突、插件能力与网络目标、ready 状态和生产降级状态校验。`backend/config/validator_security_test.go` 覆盖非法日志级别、HTTP/HTTPS 端口、ready 缺少 Web 域名、域名重复、SMTP 非法主机及远程明文、SSL 路径逃逸和证书私钥不成对、邮箱策略、插件重复/危险网络目标;`SnapshotStore` 和 `ConfigManager` 测试证明无效候选不会改变活动快照、活动代次、待重启状态或磁盘分区文件。已通过 `go test ./config ./controllers ./listen/http_server -count=1`、`go test ./... -count=1` 和 `go vet ./...`。本证据未覆盖真实数据库、真实 SMTP 投递、证书链/私钥匹配、插件进程沙箱和生产部署环境,相关验收保持开放。
### CG-008 实现统一 SecretChange 和 CredentialVault 适配
- **状态**:`[✓] 复审通过`
- **优先级**:P0
- **依赖**:CG-002、CG-005
- **设计映射**:第 3.3、10.3 章
- **修改范围**:`backend/config/secret.go`、`backend/config/sections.go`、`backend/config/manager_v2.go`、`backend/config/runtime_validator.go`、`backend/controllers/config.go`、`backend/utils/credential` 和相关测试
- **实施步骤**:实现 `keep`、`replace`、`clear`;统一数据库、SMTP、插件等凭据的加密、解密、脱敏和版本字段;插件 Secret 使用 `plugins.<逻辑ID>.secret` 变更路径,并在分区载荷中保留已有密文。
- **安全要求**:不支持旧弱算法回退;密钥文件权限不合格时拒绝启动;Secret 不进入日志。
- **测试要求**:密文篡改、错误密钥、版本不支持、三种更新语义和 JSON 脱敏测试。
- **验收标准**:所有第三方配置使用同一输入和存储边界,查询接口不返回原文。
- **回退方式**:不迁移已有凭据,只关闭 V2 写接口;不得回退成明文。
- **验收证据**:`StoredSecret`、`SecretChange`、`SecretPolicy` 和 `CredentialVault` 已统一接入数据库密码、SMTP Relay 密码和插件 Secret;插件支持 `replace`、`keep`、`clear`,未知插件、非法路径、直接提交密文均被拒绝;插件 Secret 经过同一套版本与密文格式校验,公共配置响应仅返回 `secretStatus`,不返回明文、密文或 Secret 输入值。`backend/config/secret_test.go` 覆盖三种语义、密文篡改、错误密钥、版本不支持和 JSON 脱敏;`backend/config/manager_v2_test.go` 覆盖插件 Secret 全流程及非法请求;`backend/controllers/config_public_response_test.go` 覆盖插件公共响应脱敏。测试结束清理仅匹配 `backend/.codex-smail-*` 的临时文件。已通过 `go test ./... -count=1`、`go vet ./...`、`git diff --check`,并验证 `mingw32-make clean_codex_test_artifacts` 只清理目标临时文件。真实数据库、SMTP 投递、插件进程沙箱、Ubuntu/Windows 部署和生产环境仍未完成集成验收。
### CG-009 实现不可变运行时快照
- **状态**:`[✓] 复审通过`
- **优先级**:P0
- **依赖**:CG-005、CG-007、CG-008
- **设计映射**:第 9 章
- **修改范围**:`backend/config/snapshot.go`、调用方和竞态测试
- **实施步骤**:使用 `atomic.Pointer` 发布快照;深复制映射和切片;为旧 `config.Instance` 增加只读兼容适配。
- **安全要求**:调用方不能修改已发布快照;快照不包含加密主密钥和不必要明文 Secret。
- **测试要求**:并发读取、连续更新、竞态检测、深复制和旧快照生命周期测试。
- **验收标准**:业务请求不再从磁盘读取配置,竞态测试无数据竞争。
- **回退方式**:切回旧读取适配层,不删除新快照代码。
- **验收证据**:`backend/config/snapshot.go` 使用 `atomic.Pointer[RuntimeConfig]` 和 CAS 发布;发布前对根配置、分区 map、插件 map、插件权限切片、网络目标切片和 `json.RawMessage` 深复制;拒绝低于当前活动代次的候选快照;`backend/config/runtime_access.go` 为旧 `config.Instance` 提供只读深拷贝适配;覆盖旧配置的切片和 map 字段;`backend/config/snapshot_test.go` 覆盖无效候选拒绝、输入和读取结果深拷贝、并发读取与连续更新、旧快照生命周期、旧代次并发发布;`backend/config/manager_v2_test.go` 覆盖 `Snapshot`、`UpdateResult.Candidate` 和 `ApplyResult.Snapshot` 返回值隔离;已通过 `go test ./config -count=1` 和 `go test -race ./config -count=1`;本证据未覆盖真实生产进程切换、Ubuntu/Windows 部署和真实运行时长期观测,相关验收保持开放。
### CG-010 实现 ConfigManager 核心接口
- **状态**:未开始
- **优先级**:P0
- **依赖**:CG-006、CG-007、CG-008、CG-009
- **设计映射**:第 7 章
- **修改范围**:`backend/config/manager.go`、`loader.go`、测试
- **实施步骤**:实现 `Load`、`Snapshot`、`Status`、`Validate`、`Update`、`Apply`、`Rollback`;统一错误模型。
- **安全要求**:写操作串行化;读取只返回快照;所有入口执行固定分区检查。
- **测试要求**:空配置、正常加载、分区损坏、摘要错误、代次不一致和并发更新测试。
- **验收标准**:所有配置磁盘访问由管理器控制,业务模块没有新增直接读取。
- **回退方式**:通过功能开关保持旧启动路径,V2 管理接口保持关闭。
- **验收证据**:待补充。
### CG-011 实现配置事务和崩溃恢复
- **状态**:未开始
- **优先级**:P0
- **依赖**:CG-010
- **设计映射**:第 10.1、10.2 章
- **修改范围**:`backend/config/transaction.go`、`storage.go`、`backend/utils/atomicfile`、测试
- **实施步骤**:实现候选目录、事务清单、分区提交、主入口最后提交、目录同步和启动恢复。
- **安全要求**:拒绝符号链接和非常规文件;临时文件权限与正式配置一致;崩溃后不得混合代次启动。
- **测试要求**:在每个事务阶段模拟失败;验证完成提交或恢复旧代次;执行竞态和文件替换测试。
- **验收标准**:任意受测中断点重启后只有完整新代次或完整旧代次。
- **回退方式**:停止 V2 更新并从最近有效备份加载;不手工拼接配置。
- **验收证据**:待补充。
### CG-012 实现配置备份和回滚
- **状态**:未开始
- **优先级**:P1
- **依赖**:CG-011、CG-002
- **设计映射**:第 10.4、10.5 章
- **修改范围**:`backend/config/backup.go`、`audit.go`、Controller 和测试
- **实施步骤**:每 7 天创建并验证配置备份;清理超过 30 天的备份;超过 4 份时删除最旧备份;始终保留至少一个已验证有效版本;实现超级管理员回滚预览、一次性票据和回滚生成新 generation。
- **安全要求**:新备份成功并验证后才能清理;新备份失败不得删除已有有效备份;回滚要求近期重新认证和审计;备份不含明文 Secret;不删除旧数据库、用户文件或当前唯一有效备份。
- **测试要求**:备份失败不清理、30 天边界、最多 4 份、唯一有效备份保护、备份篡改、不可解密、回滚预览票据、代次冲突、应用失败和审计失败测试。
- **验收标准**:可从受支持备份安全恢复,generation 单调递增,自动保留策略严格满足 7 天、30 天、最多 4 份和至少一个有效版本。
- **回退方式**:禁用在线回滚,仅保留只读备份。
- **验收证据**:待补充。
### CG-013 实现配置状态、数据库名称迁移、审计查询、受控重启和统一错误响应
- **状态**:未开始
- **优先级**:P1
- **依赖**:CG-010、CG-012、CG-003
- **设计映射**:第 7.3、11.7、11.8、26、27 章
- **修改范围**:`backend/dto/response`、配置 Controller、数据库名称迁移服务、审计查询和导出服务、受控服务管理器、前端请求层和测试
- **实施步骤**:实现稳定英文错误码、中文公开消息、字段错误、请求 ID、待重启服务和降级原因;实现仅限同类型同服务器同账户的数据库名称迁移服务;实现配置审计筛选、详情和脱敏导出;实现 Windows Service/systemd 固定服务重启适配器。
- **安全要求**:迁移仅限超级管理员并保留旧数据库;数据库名称迁移和配置回滚对超级管理员不检查离线恢复码,但必须要求近期重新认证或 WebAuthn 二次确认、能力授权、审计和事务保护;审计至少保留 365 天且普通 Web API 不可删除单条记录;重启不接受任意命令或服务名;响应不包含绝对路径、底层数据库错误、第三方正文或 Secret。
- **测试要求**:错误码、HTTP 状态、字段脱敏、数据库复制失败和原子切换、审计差异脱敏与导出、回滚预览票据、固定服务重启、命令注入拒绝、日志错误链和前端显示测试。
- **验收标准**:配置相关接口不再使用模糊空错误或直接返回底层错误;数据库名称迁移失败继续使用旧库;审计和重启均通过受控服务边界。
- **回退方式**:保留旧响应兼容外壳,内部仍使用新错误模型。
- **验收证据**:待补充。
### 第二阶段验收
- [ ] 配置模型和固定分区映射完成;
- [ ] 严格 JSON、语义校验和 Secret 统一边界完成;
- [ ] 不可变快照和 ConfigManager 完成;
- [ ] 配置事务、崩溃恢复、备份和回滚通过测试;
- [ ] 数据库名称迁移、完整审计和受控重启服务边界完成;
- [ ] 所有配置错误响应完成脱敏。
---
## 6. 第三阶段:SSL、插件、SMTP 和邮箱分区
### CG-014 实现旧 config.json 到分区配置迁移
- **状态**:未开始
- **优先级**:P0
- **依赖**:CG-010、CG-011、CG-003
- **设计映射**:第 11 章
- **修改范围**:`backend/config/migrate.go`、迁移测试和示例配置
- **实施步骤**:检测旧结构;生成迁移计划;映射基础、SSL、SMTP、插件字段;重新封装凭据;完整验证后提交新主入口。
- **安全要求**:迁移前备份;未知字段必须报告;无法安全解密的凭据要求重新设置;不删除旧文件。
- **测试要求**:当前配置、缺失字段、未知字段、损坏密文、重复执行和迁移中断测试。
- **验收标准**:迁移结果可由 ConfigManager 加载,旧文件仍保留且未被覆盖。
- **回退方式**:停用 V2 启动开关并加载迁移前备份。
- **验收证据**:待补充。
### CG-015 拆分 SSL 配置和受控证书存储
- **状态**:[x] 已完成,等待复审
- **优先级**:P1
- **依赖**:CG-014、CG-007
- **设计映射**:第 6、8、11.6、12、30 章
- **修改范围**:`backend/config/ssl.go`、`backend/services/setup/ssl`、`backend/listen/http_server`、测试
- **实施步骤**:实现 `managed_default` 默认受控目录和 `managed_upload` 自定义上传后托管双模式;导入证书到候选目录并生成内部引用;完成证书链、私钥匹配和域名校验后原子切换;接入快照和应用结果。
- **安全要求**:API 不接受服务器绝对路径;限制大小和 PEM 类型;拒绝路径逃逸、符号链接、重解析点和硬链接;检查私钥权限;生产环境不得因证书错误自动回退到公网 HTTP。
- **测试要求**:默认目录、自定义上传、自动证书、路径输入拒绝、路径逃逸、符号链接、重解析点、硬链接、权限、域名不匹配和更新回滚测试。
- **验收标准**:两种托管模式均只保存内部引用,SSL 服务不再读取旧聚合字段,错误时进入受控降级状态。
- **回退方式**:切回旧只读适配层,不覆盖已保存证书。
- **验收证据**:
- 2026年8月28日完成受控 SSL 存储实现:`managed_default` 和 `managed_upload` 均写入候选目录后切换 `current`,配置仅保存内部引用;旧聚合路径字段保留为只读兼容适配,不再由 HTTPS、SMTP、IMAP、POP3 监听服务直接读取。
- 已覆盖证书链、私钥匹配、有效期、域名/SAN、RSA/ECDSA 密钥强度、文件大小、PEM 类型、路径穿越、绝对路径、Windows 盘符路径、UNC 路径、符号链接、硬链接、私钥权限、更新回滚和运行时证书加载测试。
- `go test ./... -count=1` 通过。
- `go test -race ./... -count=1` 通过。
- `go vet ./...` 通过。
- `git diff --check` 通过。
- 尚未完成 Ubuntu 22.04 实机证书部署/轮换、Windows 重解析点真实系统测试及 HTTPS、SMTP、IMAP、POP3 生产启动验收;这些边界保留待复审。
### CG-016 建立插件目录和逻辑 ID 清单
- **状态**:[✓] 复审通过
- **优先级**:P0
- **依赖**:CG-005、CG-002
- **设计映射**:第 21.1 章
- **修改范围**:`backend/services/plugin/catalog.go`、`backend/hooks/registry.go`、测试
- **实施步骤**:固定 `spam_block`、`wechat_push`、`telegram_push`;建立跨平台可执行文件映射和插件能力元数据。
- **安全要求**:不接受客户端路径;拒绝未知插件 ID、重复 Hook 名和未登记可执行文件。
- **测试要求**:路径注入、大小写冲突、重复 ID、未知文件和平台映射测试。
- **验收标准**:插件启用决策完全基于逻辑 ID,不再基于任意文件扫描结果。
- **回退方式**:保持插件全部停用,不恢复任意目录扫描。
- **验收证据**:`go test ./plugins/catalog -count=1` 通过;目录能力、握手能力、设置字段、逻辑 ID 和跨平台可执行文件映射测试通过。
### CG-017 实现插件全局配置、用户设置和对象级授权
- **状态**:[✓] 复审通过
- **优先级**:P0
- **依赖**:CG-008、CG-016、CG-002
- **设计映射**:第 13.3、14.4、21.2~21.5 章
- **修改范围**:`backend/config/plugins.go`、`backend/services/plugin/config.go`、`user_setting.go`、`secret.go`、数据库迁移、模型和测试
- **实施步骤**:实现非敏感全局插件 DTO、`plugin_user_setting`、`plugin_secret`、按插件验证器、本人设置服务、跨用户设置服务、批量预览与执行服务;插件 Secret 使用统一 SecretChange 加密存数据库;Telegram 用户设置只存数据库;预留能力授权接口但暂不开放写路由。
- **安全要求**:主密钥不能存入同一数据库;插件文件和配置备份不得包含 Token、Secret、API Key;本人服务只从 Session 获取用户 ID;跨用户服务校验目标角色;批量服务只接受短时一次性预览票据、明确覆盖策略和逐用户版本;正式路由在 CG-025 完成前保持关闭。
- **测试要求**:三角色策略、IDOR、批量目标篡改、预览票据重放、版本冲突、数据库密文篡改、密钥分离、Secret 脱敏、Telegram 用户设置归属和并发更新测试。
- **验收标准**:本人、跨用户和批量服务边界已分离;插件 Secret 只以数据库密文保存;任何调用者都不能通过修改 `userId`、目标集合或插件 ID 越权;未接入能力授权前不存在可访问写路由。
- **回退方式**:关闭用户设置写接口,保留已保存数据但不下发插件。
- **验收证据**:`go test ./services/plugin -count=1` 通过;三角色、IDOR、批量票据、版本冲突、密文篡改、密钥分离和 Secret 状态脱敏测试通过。
### CG-018 实现插件专属配置下发和 RPC 生命周期
- **状态**:[✓] 复审通过
- **优先级**:P0
- **依赖**:CG-016、CG-017、CG-009
- **设计映射**:第 21.4、22 章
- **修改范围**:`backend/services/plugin`、`backend/hooks/base.go`、`backend/hooks/framework`、测试
- **实施步骤**:增加 `/Capabilities`、`/ValidateConfig`、`/Configure`、`/Health`;生成单插件裁剪 DTO;只在内存解密并下发该插件所需 Secret;实现目标主机、端口和协议强制白名单;将 Web Push 纳入插件能力;在健康检查后注册 Hook。
- **安全要求**:插件只获取自身配置和当前事件必要用户设置;RPC 有认证、大小、超时和并发限制;网络默认拒绝且不存在任意外网开关;每次 DNS 解析、重定向和连接均校验白名单;失败立即注销 Hook。
- **测试要求**:伪造插件、超大响应、超时、崩溃、重复 Hook、错误能力、Secret 泄露、主机和端口绕过、DNS 重绑定、跨白名单重定向、私网访问和 Web Push 越权测试。
- **验收标准**:抓取插件通信内容时不存在主配置、DSN、其他插件配置或无关用户设置,任何网络连接均命中明确白名单和能力授权。
- **回退方式**:停用插件,不回退到复制完整配置文件。
- **验收证据**:`go test ./hooks/... -count=1` 通过;握手集合、配置代次、插件能力、响应上限、Secret 隔离和 Hook 注册前健康检查测试通过。
### CG-019 改造 spam_block 插件源码
- **状态**:[✓] 复审通过
- **优先级**:P1
- **依赖**:CG-018
- **设计映射**:第 21~22 章
- **修改范围**:`plugins/spam_block`、对应主程序适配和测试
- **实施步骤**:移除旧 PMail 配置依赖;实现标准能力和配置端点;只接收垃圾邮件策略 DTO;补充健康检查。
- **安全要求**:不读主配置和主数据库;输入邮件和配置有大小限制;规则错误不得导致进程失控。
- **测试要求**:正常规则、恶意正则或超长输入、错误配置、RPC 重放和进程退出测试。
- **验收标准**:插件可由新管理器启动、配置、检查并处理 Hook,源码不再引用旧主配置包。
- **回退方式**:禁用 `spam_block`,核心邮件服务继续运行。
- **验收证据**:`go test ./hooks/spam_block -count=1` 通过;配置代次、能力权限、网络白名单、超长输入和尾随 JSON 拒绝测试通过。
### CG-020 改造 wechat_push 插件源码
- **状态**:[✓] 复审通过
- **优先级**:P1
- **依赖**:CG-018
- **设计映射**:第 21~22 章
- **修改范围**:`plugins/wechat_push`、对应主程序适配和测试
- **实施步骤**:移除读取 `config.json` 和独立配置文件逻辑;接收加密管理后的专属 DTO;实现配置验证和健康检查。
- **安全要求**:Secret 只由主程序短暂下发;限制微信 API 目标、请求大小和超时;日志不得输出 Secret 或完整响应。
- **测试要求**:凭据缺失、无效响应、超时、SSRF 目标替换、用户配置越权和脱敏测试。
- **验收标准**:插件运行不需要磁盘配置,网络只能访问授权目标。
- **回退方式**:禁用 `wechat_push`,保留配置密文。
- **验收证据**:`go test ./hooks/wechat_push -count=1` 通过;Secret 脱敏、配置代次、能力权限、网络目标、域名校验和尾随 JSON 拒绝测试通过。
### CG-021 改造 telegram_push 插件源码
- **状态**:[✓] 复审通过
- **优先级**:P1
- **依赖**:CG-018
- **设计映射**:第 21~22 章
- **修改范围**:`plugins/pmail_telegram_push`、对应主程序适配和测试
- **实施步骤**:移除旧 PMail 配置依赖;Bot Token 使用全局 Secret;Chat ID 使用用户级配置;实现配置测试和健康检查。
- **安全要求**:普通用户不能获取 Bot Token;管理员不能修改其他管理员配置;限制 Telegram API 目标和响应大小。
- **测试要求**:三角色配置矩阵、Chat ID 校验、Token 脱敏、网络失败、错误响应和事件用户映射测试。
- **验收标准**:全局 Token 和用户 Chat ID 完全分离,插件只接收当前事件所需用户配置。
- **回退方式**:禁用 `telegram_push`,不将 Token 写回旧配置。
- **验收证据**:`go test ./plugins/pmail_telegram_push/... -count=1` 通过;三角色配置服务、Chat ID、Token 脱敏、配置代次、网络目标和设置字段测试通过。
### CG-022 拆分 SMTP 和邮箱策略配置
- **状态**:未开始
- **优先级**:P1
- **依赖**:CG-014、CG-009
- **设计映射**:第 6、8、30 章
- **修改范围**:`backend/config/smtp.go`、`email.go`、SMTP/IMAP/POP3 服务和测试
- **实施步骤**:迁移监听、DKIM、垃圾邮件、Relay 和邮箱策略字段;按热更新或重启分类;业务服务改读快照。
- **安全要求**:SMTP 密码统一加密;DKIM 私钥限制受控目录;连接测试执行 SSRF 防护。
- **测试要求**:端口冲突、DKIM 路径、Relay 凭据、策略边界、应用失败和服务重启测试。
- **验收标准**:邮件服务不再依赖旧聚合配置字段,配置错误不会带错启动。
- **回退方式**:使用旧只读适配层并保持新配置只读,不回退 Secret 保护。
- **验收证据**:待补充。
### 第三阶段验收
- [ ] 旧配置可安全迁移且原文件未删除;
- [ ] SSL、SMTP 和邮箱策略已拆分并由快照读取;
- [ ] 三个插件源码完成新配置协议改造;
- [ ] 插件只接收自身和当前用户必要配置;
- [ ] 插件 Secret 只以数据库密文保存且主密钥分离;
- [ ] 插件网络强制白名单和 Web Push 能力边界通过测试;
- [ ] 本人、跨用户和批量插件设置服务已分离,批量修改必须先预览;
- [ ] 插件用户设置写路由在第四阶段能力授权完成前保持关闭;
- [ ] 插件失败不会影响核心服务。
---
## 7. 第四阶段:三级角色、数据库迁移和统一认证
### CG-023 迁移 user 角色和安全字段
- **状态**:未开始
- **优先级**:P0
- **依赖**:CG-003、CG-001
- **设计映射**:第 14.1、24.1、24.2 章
- **修改范围**:`backend/models/User.go`、数据库迁移、用户服务和测试
- **实施步骤**:增加 `role`、`must_change_password`、`security_version`、密码时间字段;迁移现有 `is_admin`;保留兼容输出。
- **安全要求**:无法唯一确定首个超级管理员时停止迁移;至少保留一个未禁用超级管理员。
- **测试要求**:零管理员、一个管理员、多个管理员、禁用管理员和重复迁移测试。
- **验收标准**:所有现有用户映射正确,授权读路径可只使用 `role`。
- **回退方式**:保留 `is_admin` 列和双读对照,不删除新字段。
- **验收证据**:待补充。
### CG-024 实现能力授权器
- **状态**:未开始
- **优先级**:P0
- **依赖**:CG-002、CG-023
- **设计映射**:第 13.1~13.4 章
- **修改范围**:新增 `backend/services/access`、上下文和测试
- **实施步骤**:定义角色、能力、默认矩阵、资源引用和目标用户策略;将插件启停与插件重启拆分为 `plugin.control` 和 `plugin.restart`;在请求上下文中装载后端能力。
- **安全要求**:默认拒绝;不得通过角色字符串排序;目标资源和目标角色必须同时检查。
- **测试要求**:三角色能力矩阵、管理员仅重启明确授权插件、未知角色、角色变化、禁用用户和目标用户边界测试。
- **验收标准**:授权器成为所有新管理 API 的唯一能力判断入口。
- **回退方式**:关闭新管理 API,不回退为仅检查 `IsAdmin`。
- **验收证据**:待补充。
### CG-025 切换现有管理接口到能力授权
- **状态**:未开始
- **优先级**:P0
- **依赖**:CG-024、CG-017
- **设计映射**:第 13.3~13.5、23 章
- **修改范围**:`backend/controllers/plugin.go`、`user.go`、`settings.go`、`group.go`、`rule.go` 和路由测试
- **实施步骤**:逐接口替换布尔管理员判断;增加对象级策略;分离角色变更 DTO;保护最后一个超级管理员;角色变更时按照变更后的目标角色检查有效恢复码;启用已完成授权接入的本人、跨用户和批量插件设置路由。
- **安全要求**:直接调用隐藏接口仍拒绝;角色变更和高风险配置要求二次确认;目标角色为管理员或普通用户时必须已经配置有效恢复码,否则返回稳定错误码 `RECOVERY_CODE_REQUIRED`;目标角色为超级管理员时明确豁免恢复码检查;管理员不能管理管理员;普通用户不能访问含目标用户 ID 的插件接口;批量插件接口仅限超级管理员。
- **测试要求**:接口级权限矩阵、IDOR、批量操作、管理员和普通用户恢复码前置条件、超级管理员豁免、稳定错误码、并发降级最后超级管理员和旧 Session 测试。
- **验收标准**:受测管理接口不再以 `ctx.IsAdmin` 作为最终授权依据。
- **回退方式**:关闭受影响管理写接口,不恢复宽松旧判断。
- **验收证据**:待补充。
### CG-026 实现用户邮箱绑定和登录标识解析器
- **状态**:未开始
- **优先级**:P0
- **依赖**:CG-003、CG-023
- **设计映射**:第 14.2、15.1、15.2 章
- **修改范围**:`backend/models/user_email.go`、数据库迁移、`backend/services/auth/identifier.go`、测试
- **实施步骤**:增加邮箱规范化字段和唯一索引;实现用户名或完整邮箱精确解析;移除截断域名逻辑。
- **安全要求**:冲突绑定必须停止迁移或拒绝登录;邮箱不存在时保持防枚举和耗时一致。
- **测试要求**:用户名、完整邮箱、域名大小写、本地部分、重复邮箱、未验证邮箱、多个 `@` 和超长输入测试。
- **验收标准**:`name@example.com` 只能通过真实绑定记录解析,绝不自动变成 `name`。
- **回退方式**:关闭邮箱登录,只保留用户名精确登录;不得恢复截断域名。
- **验收证据**:待补充。
### CG-027 实现 Web 和邮件协议统一认证器
- **状态**:未开始
- **优先级**:P0
- **依赖**:CG-026、CG-024
- **设计映射**:第 15.3 章
- **修改范围**:`backend/services/auth`、SMTP、IMAP、POP3 登录处理和测试
- **实施步骤**:实现统一 `Authenticator`;接入四个通道;复用标识解析、密码验证、用户状态和审计。
- **安全要求**:统一虚假哈希;账户、IP、组合限流;协议层不得复制密码校验或账号截断。
- **测试要求**:同一用户通过两种标识在四通道登录;错误耗时、禁用用户、限流和协议差异测试。
- **验收标准**:Web、SMTP、IMAP、POP3 的凭据判断结果一致。
- **回退方式**:逐通道关闭新认证开关,但保留用户名精确解析和当前密码算法。
- **验收证据**:待补充。
### CG-028 升级登录 API、Session 和前端状态响应
- **状态**:未开始
- **优先级**:P1
- **依赖**:CG-027、CG-023
- **设计映射**:第 15.1、15.4、15.5 章
- **修改范围**:`backend/controllers/login.go`、`backend/session`、`frontend/src/views/LoginView.vue`、Store 和测试
- **实施步骤**:将请求字段迁移到 `identifier`;返回角色、能力和安全引导状态;Session 绑定版本;支持临时密码限制。
- **安全要求**:`account` 兼容字段有冲突时拒绝;Session 固定防护、CSRF 和安全 Cookie 保持有效。
- **测试要求**:旧新 DTO 冲突、登录成功响应、角色变化、密码变化、临时密码和 Session 撤销测试。
- **验收标准**:前端不再依赖 `is_admin` 决定权限,登录错误不泄露账户状态。
- **回退方式**:短期保留 `account` 兼容输入和 `is_admin` 计算输出,不恢复旧授权。
- **验收证据**:待补充。
### CG-029 统一密码策略、修改和参数升级
- **状态**:未开始
- **优先级**:P0
- **依赖**:CG-027
- **设计映射**:第 16.1、16.2 章
- **修改范围**:`backend/services/auth/password.go`、`backend/utils/password`、安全设置接口和测试
- **实施步骤**:统一新密码策略;封装 Argon2id;实现 `NeedsRehash`;管理员和普通用户修改密码时递增 Session 版本,撤销包括当前会话在内的全部旧 Session,成功响应后清除当前 Session Cookie,并要求使用新密码重新登录;Web 接口显式拒绝超级管理员。
- **安全要求**:不随机选择算法;不保留旧算法无限回退;密码不出现在日志、URL 和审计;超级管理员不能通过任何 Web 路由修改或恢复密码。
- **测试要求**:弱密码、同密码、超长输入、参数升级、并发修改、事务失败和超级管理员直接调用 Web 改密接口测试。
- **验收标准**:创建、修改、恢复和管理员重置全部调用同一密码服务。
- **回退方式**:保持当前 Argon2id 参数,不回退旧算法。
- **验收证据**:待补充。
### CG-030 实现分角色跨用户密码重置
- **状态**:未开始
- **优先级**:P1
- **依赖**:CG-025、CG-029、AD-021
- **设计映射**:第 16.3、23.5 章
- **修改范围**:用户 Controller、认证服务、审计和前端用户管理
- **实施步骤**:增加分角色跨用户重置接口;超级管理员可重置管理员和普通用户,管理员仅可重置普通用户,普通用户只能通过本人恢复流程重置自己;生成一次性临时密码并设置强制修改;在同一事务中撤销目标全部 WebAuthn 凭据、全部旧离线恢复码、全部登录 Session、未完成恢复流程和重置票据;递增 Session、Security、Credential 版本;设置下次登录生成新恢复码并提示重新绑定 WebAuthn;向已验证外部安全邮箱发送通知并记录审计。
- **安全要求**:任何 Web 角色都不能重置超级管理员;管理员不能重置管理员;跨用户操作要求近期重新认证或 WebAuthn 二次确认;临时密码最多展示一次;不得生成 WebAuthn 私钥;任一撤销或审计步骤失败时不得部分提交密码重置。
- **测试要求**:操作者角色×目标角色完整矩阵、普通用户仅本人恢复、越权管理员、重复请求、WebAuthn 撤销、恢复码整组撤销、全部 Session 撤销、恢复流程和票据撤销、三类版本递增、通知失败、审计失败、事务回滚和临时密码泄露测试。
- **验收标准**:超级管理员可重置管理员和普通用户,管理员可重置普通用户,普通用户仅可重置本人;重置后全部旧安全凭据和会话失效;目标下次登录必须改密、生成新恢复码并重新绑定 WebAuthn。
- **回退方式**:关闭重置接口,不影响用户主动修改密码。
- **验收证据**:待补充。
### CG-031 实现超级管理员部署端专用密码重置通道
- **状态**:`[~] 进行中`
- **优先级**:P0
- **依赖**:CG-029、CG-023、AD-006~AD-020、AD-062、AD-063
- **设计映射**:第 16.4 章
- **修改范围**:`backend/cmd/smail-admin/main.go`、专用重置通道服务、systemd unit、Windows 服务适配、Windows Named Pipe、Unix Domain Socket 和测试
- **实施步骤**:随主程序安装独立 `smail-admin`;Linux 唯一正式可写入口固定为显式 `systemctl start smail-admin`,`systemctl stop smail-admin` 仅用于终止正在运行的短时事务;禁止开机自启动、自动重启、reload、restart、try-restart 和依赖拉起进入重置流程;由短时一次性 systemd 服务执行一个受控重置事务后退出;使用 `systemd-ask-password` 或等效受保护本机密码代理获取不回显的新密码;经 Unix Domain Socket 调用主程序统一密码服务;Windows 使用等价服务启动语义和 Named Pipe;使用 `closed -> open -> consumed` 或 `closed -> open -> expired` 状态机;成功、超时、失败达到阈值或管理进程退出后自动关闭通道。
- **安全要求**:不监听公网、局域网或 localhost TCP;不注册普通 HTTP Router;不能由 Web、公共 API、环境变量、普通配置、插件、开发模式、开机目标、服务依赖或非 start systemd Job 开启;没有安全密码代理时拒绝执行;密码不得通过命令参数、标准输入、标准输出、环境变量、文件、服务名或日志传递;Unix Socket 权限和对端身份必须校验,Windows Named Pipe 仅允许受信系统身份;失败不得降级为普通 Web 重置流程。`status`、`show`、`is-active` 等只读命令只允许观察状态,不创建重置会话。
- **测试要求**:在 Windows、Ubuntu 22.04 和 Ubuntu 24.04 验证正式服务入口和平台适配器;执行无开机自启动、start、stop、restart、try-restart、reload、依赖拉起、只读状态查询、TCP/HTTP 暴露扫描、systemd 安全密码代理缺失、Named Pipe 和 Unix Socket 权限与对端身份、维护会话重放、跨进程复用、通道超时、管理进程退出、失败阈值、参数/标准输入输出/环境变量/文件/日志泄漏、普通 Web API 尝试开启通道、开发模式自动开放、Session 与安全版本撤销测试。
- **验收标准**:超级管理员不能通过离线恢复码、外部安全邮箱验证码或普通 Web 流程重置密码;Linux 只能通过显式 `systemctl start smail-admin` 启动受控重置事务,`stop` 只能终止,其他 systemd 动作不能进入重置流程;独立程序、systemd unit、安全密码代理、本机 IPC、Windows 和 Ubuntu 平台适配器及全部安全测试未完成前,本任务和本轮重构均不得最终验收。
- **回退方式**:完全禁用维护服务,不提供公网替代接口。
- **验收证据**:已实现 Linux oneshot unit、禁止安装启用、历史 enable 清理、systemd 启动上下文和显式 start Job 校验及静态策略测试;Go 定向测试已通过。Ubuntu 22.04/24.04 真实 systemd 行为和完整跨平台验收尚未完成。
- `[x] 已完成,等待复审`:Linux unit 和安装脚本的手动启动边界。
- `[x] 已完成,等待复审`:非 start Job、直接执行和非受信 systemd 上下文拒绝逻辑。
- `[!] 暂缓或存在阻塞`:Ubuntu 22.04/24.04 真机验证、Windows 等价服务启动限制和完整本机 IPC 安全验收仍未完成。
### 第四阶段验收
- [ ] 用户角色迁移完成且至少保留一个超级管理员;
- [ ] 所有管理接口使用能力和资源级授权;
- [ ] 用户名和完整邮箱解析无歧义;
- [ ] Web、SMTP、IMAP、POP3 认证结果一致;
- [ ] 密码修改和重置统一使用当前 Argon2id 服务;
- [ ] 超级管理员重置后旧 WebAuthn、恢复码、Session、恢复流程和票据全部撤销;
- [ ] 超级管理员本地维护通道无网络暴露。
---
## 8. 第五阶段:密保、离线恢复码和 WebAuthn
### CG-032 创建账户恢复数据表和仓储
- **状态**:未开始
- **优先级**:P0
- **依赖**:CG-003、CG-023
- **设计映射**:第 14.3、17~20、24 章
- **修改范围**:数据库迁移、`backend/models`、`backend/services/auth` 仓储和测试
- **实施步骤**:创建密保、恢复码、WebAuthn、密码重置和安全审计通用数据表;建立唯一索引、外键、版本字段和过期查询;为 AD-022~AD-025、AD-035~AD-037 提供三数据库迁移基础,但外部邮箱和验证码非敏感运营数据的详细字段由对应 AD 任务实现。
- **安全要求**:答案、恢复码和票据只保存不可逆值;WebAuthn credential ID 全局唯一;不得创建可持久化验证码、验证码校验值、内存验证码任务或进程临时密钥的字段和表。
- **测试要求**:三种数据库建表、重复迁移、约束冲突、时间字段、禁止验证码秘密字段和事务回退测试。
- **验收标准**:所有通用恢复数据具有明确归属、状态、版本和过期字段,并为 AD 子任务提供不突破仅内存验证码边界的迁移基础。
- **回退方式**:保持新表不被旧代码使用;不删除已生成安全数据。
- **验收证据**:待补充。
### CG-033 实现密保问题和答案服务
- **状态**:未开始
- **优先级**:P0
- **依赖**:CG-032、CG-029
- **设计映射**:第 17 章
- **修改范围**:`backend/services/auth/security_question.go`、Controller、前端接口和测试
- **实施步骤**:实现问题设置、答案固定规范化、Argon2id 哈希、独立随机盐、算法与规范化版本、修改验证、限流和恢复阶段验证;规范化固定为去除首尾空格、Unicode 规范化、英文转小写、合并连续空白,并保留标点和特殊字符。
- **安全要求**:答案不可逆保存;密保问答不能单独重置密码;不使用模糊匹配、随机算法或可逆加密;问题和答案不得写日志。
- **测试要求**:大小写混淆、Unicode 等价、首尾和连续空白、标点保留、版本升级、错误答案、防枚举、限流、修改撤销恢复会话和单因素绕过测试。
- **验收标准**:只有通过受控恢复会话才能验证答案,正确答案也不能直接获得密码重置权。
- **回退方式**:关闭忘记密码入口,保留用户设置数据。
- **验收证据**:待补充。
### CG-034 实现离线恢复码生成和一次性展示
- **状态**:未开始
- **优先级**:P0
- **依赖**:CG-032、CG-029
- **设计映射**:第 18.1~18.4 章
- **修改范围**:`backend/services/auth/recovery_code.go`、安全接口、前端状态和测试
- **实施步骤**:使用安全随机源生成一组代码;保存不可逆校验值;一次返回明文;实现状态和剩余数量接口。
- **安全要求**:要求近期重新认证;响应 `no-store`;明文不进入数据库、日志、审计、Store 持久化或 URL。
- **测试要求**:随机源失败、事务失败、响应缓存头、重复查看、重新生成和前端存储检查。
- **验收标准**:明文只能在生成成功的当前响应中看到一次,后端不能恢复原文。
- **回退方式**:关闭生成入口;不删除已有恢复码记录。
- **验收证据**:待补充。
### CG-035 实现离线恢复码原子消费、撤销和并发保护
- **状态**:未开始
- **优先级**:P0
- **依赖**:CG-034
- **设计映射**:第 18.5、18.6 章
- **修改范围**:恢复码服务、数据库仓储、审计和并发测试
- **实施步骤**:按未使用条件更新;消费与重置票据创建同事务;重新生成撤销整组;支持用户主动撤销。
- **安全要求**:同一代码并发请求最多成功一次;验证失败统一响应;审计不记录代码或哈希。
- **测试要求**:高并发双花、事务回滚、已用代码、旧组代码、撤销后代码和限流测试。
- **验收标准**:所有受测并发场景只有一个成功消费者,失败不会产生有效票据。
- **回退方式**:关闭恢复码验证入口,保留已生成状态供后续恢复。
- **验收证据**:待补充。
### CG-036 实现 WebAuthn 注册和凭据管理
- **状态**:未开始
- **优先级**:P0
- **依赖**:CG-032、CG-028
- **设计映射**:第 19.1~19.3、19.5 章
- **修改范围**:`backend/services/auth/webauthn.go`、Controller、前端组件和测试
- **实施步骤**:生成注册 Challenge;绑定用户、Session、RP ID、Origin 和有效期;验证注册响应;实现列表、重命名和撤销。
- **安全要求**:Challenge 一次性;credential ID 全局唯一;校验用户验证标志;生产只允许配置的 HTTPS Origin。
- **测试要求**:Challenge 重放、跨用户绑定、错误 Origin、错误 RP ID、过期、取消、签名数据篡改和撤销测试。
- **验收标准**:用户可自选启用,其他用户和管理员不能替其注册或读取私钥材料。
- **回退方式**:关闭 WebAuthn 新注册,保留已有凭据数据但不弱化恢复流程。
- **验收证据**:待补充。
### CG-037 实现 WebAuthn 恢复断言验证
- **状态**:未开始
- **优先级**:P0
- **依赖**:CG-033、CG-036
- **设计映射**:第 19.4、20 章
- **修改范围**:WebAuthn 恢复服务、Controller 和测试
- **实施步骤**:在有效恢复会话中生成断言 Challenge;限制允许凭据;验证签名、用户归属、Origin、RP ID、用户验证和签名计数。
- **安全要求**:断言只推进当前恢复会话,不能直接创建登录 Session;异常计数产生安全事件。
- **测试要求**:跨账户凭据、Challenge 重放、错误签名、克隆计数、过期和绕过密保阶段测试。
- **验收标准**:只有已经通过密保问答的恢复会话可使用绑定安全密钥获得重置票据。
- **回退方式**:关闭 WebAuthn 恢复选项,仍要求有效离线恢复码。
- **验收证据**:待补充。
### CG-038 实现完整忘记密码状态机
- **状态**: [~] 进行中
- **优先级**:P0
- **依赖**:CG-033、CG-035、CG-037、CG-029
- **设计映射**:第 20 章
- **修改范围**:`backend/services/auth/recovery.go`、恢复 Controller、路由和测试
- **实施步骤**:实现统一恢复状态机和路径 A:开始、密保问题验证、离线恢复码或 WebAuthn 验证、票据签发、新密码设置、完成和过期;建立路径 B 的正式状态、接口和事务边界,供 AD-043~AD-047 完整实现外部安全邮箱验证码恢复;任一路径成功后撤销全部旧会话和未完成恢复票据;功能启用且配置有效域名或 IP 时注册固定 `/Reset` 页面入口,并由同一后端开关保护全部恢复 API。
- **安全要求**:仅管理员和普通用户使用;路径 A 必须为密保问答加恢复码或 WebAuthn;路径 B 必须完成验证码服务、SMTP 投递、外部邮箱验证、限流、审计和清理并通过安全验收后才能启用,配置错误或投递失败时安全拒绝且不得降级绕过;票据高熵、短期、一次性且只存哈希。
- **测试要求**:路径 A 全部合法流程、阶段跳过、阶段回退、票据重放、并发流程、防枚举和超级管理员禁用;路径 B 覆盖默认关闭、完整启用、配置错误、投递失败、验证码错误或过期、跨用途重放和并发消费,关闭或失败时不能创建有效重置票据。
- **验收标准**:两条正式恢复路径共享统一状态机和密码服务;路径 B 的完整实现由 AD-043~AD-047、AD-050、AD-053 提供,相关 AD 任务和安全验收未完成前保持不可用,但不得作为“本轮不实现”的理由。
- **回退方式**:关闭 Web 忘记密码入口,由超级管理员重置管理员和普通用户。
- **验收证据**:2026-08-27 已完成 `/Reset` 域名/IP入口、方法和开关边界、独立恢复页及自动化测试;密保问答路径和完整浏览器验收仍未完成。
- [x] 已完成,等待复审:`/Reset` 仅在 `ready`、启用恢复且存在有效域名/IP时开放。
- [x] 已完成,等待复审:HTTP 在生产环境继续保持 HTTPS 跳转,不新增超级管理员 Web 重置路径。
- [!] 暂缓或存在阻塞:CG-038 其余恢复路径尚未全部完成,整体保持进行中。
### CG-039 实现恢复流程统一限流、审计和失效策略
- **状态**:未开始
- **优先级**:P1
- **依赖**:CG-038
- **设计映射**:第 17.4、20.6、26 章
- **修改范围**:认证限流器、安全审计、清理任务和测试
- **实施步骤**:按账户、IP、流程和设备限制;定义锁定时间;清理过期 Challenge 和票据;密码或安全设置变化时撤销旧流程。
- **安全要求**:响应和耗时避免账户枚举;限流键不能被大小写、邮箱别名或代理头绕过。
- **测试要求**:多维绕过、代理头伪造、并发流程、锁定恢复、清理容量和审计脱敏测试。
- **验收标准**:暴力尝试被稳定限制,安全事件可追踪且不泄露凭据。
- **回退方式**:关闭恢复入口,不关闭正常登录限流。
- **验收证据**:待补充。
### 第五阶段验收
- [ ] 密保问答不能单独重置密码;
- [ ] 密保答案大小写不敏感规范化、Argon2id 和版本字段通过测试;
- [ ] 恢复码只能展示一次并且只能消费一次;
- [ ] WebAuthn 由用户自选启用且验证完整;
- [ ] 路径 A 只接受密保问答加离线恢复码或 WebAuthn;
- [ ] 外部安全邮箱验证码路径 B 默认关闭且不能降级绕过路径 A;
- [ ] 超级管理员不能使用 Web 忘记密码;
- [ ] 密码恢复成功后旧 Session 和旧流程全部失效。
---
## 9. 第六阶段:管理页面和账户安全页面
### CG-040 重构前端认证状态和能力守卫
- **状态**:未开始
- **优先级**:P0
- **依赖**:CG-028、CG-025
- **设计映射**:第 25.2、25.3 章
- **修改范围**:`frontend/src/stores`、`frontend/src/router`、`frontend/src/utils/axios.js`、测试
- **实施步骤**:新增认证 Store;保存角色、能力和安全状态;实现路由守卫和操作级能力组件;统一 401、403 和二次认证处理。
- **安全要求**:前端守卫不替代后端;不持久化 Secret、Challenge 和恢复票据;不在控制台打印敏感请求。
- **测试要求**:三角色路由、直接输入 URL、角色变化、Session 过期、403 和 Store 清理测试。
- **验收标准**:页面显示与后端能力一致,退出后安全状态完全清理。
- **回退方式**:退回只读页面并关闭管理写操作,不恢复前端管理员布尔判断。
- **验收证据**:待补充。
### CG-041 实现分区配置管理页面
- **状态**:未开始
- **优先级**:P1
- **依赖**:CG-013、CG-040
- **设计映射**:第 11.7、11.8、23.2、25.1、25.2、26 章
- **修改范围**:`frontend/src/components`、配置 Store、路由和测试
- **实施步骤**:实现配置状态、基础、SMTP、邮箱策略、SSL、数据库名称迁移和超级管理员配置审计页面;显示 generation、验证结果、应用方式和待重启状态;实现回滚预览、脱敏 CSV/JSON 导出和“重启 Smail”按钮。
- **安全要求**:Secret 只显示“已配置”;差异中的 Secret 只显示已设置、已修改、已清除;保存和回滚使用明确操作及近期重新认证;冲突时不得自动覆盖;迁移页不接收主机、账户、密码或 DSN;重启页不接收命令和服务名。
- **测试要求**:加载、编辑、验证、代次冲突、连接测试、数据库迁移阶段、应用失败、审计筛选和详情、导出审计、回滚预览票据、受控重启、权限拒绝和响应脱敏测试。
- **验收标准**:超级管理员能完成受控配置、数据库名称迁移、完整脱敏审计、回滚和重启流程,管理员只能看到授权的脱敏状态且不能访问这些高风险页面。
- **回退方式**:页面切为只读状态,不绕过 ConfigManager 直接保存。
- **验收证据**:待补充。
### CG-042 实现分角色插件和用户管理页面
- **状态**:未开始
- **优先级**:P1
- **依赖**:CG-017、CG-021、CG-040
- **设计映射**:第 21、23.3、25.5 章
- **修改范围**:`frontend/src/components/PluginSettings.vue`、`UserManagement.vue`、Store 和测试
- **实施步骤**:按能力展示全局、普通用户和自己的设置;使用 Schema 驱动中文表单;显示插件健康状态和脱敏测试结果。
- **安全要求**:不渲染插件任意 HTML;不信任前端 `userId`;Secret 不回填;测试请求限制目标。
- **测试要求**:三角色页面矩阵、篡改用户 ID、隐藏按钮直调、Secret 浏览器存储和插件失败测试。
- **验收标准**:超级管理员、管理员、普通用户分别只能看到和修改允许范围。
- **回退方式**:关闭插件设置页面和插件写接口,保持插件停用或旧有效运行配置。
- **验收证据**:待补充。
### CG-043 扩展账户安全页面
- **状态**:未开始
- **优先级**:P1
- **依赖**:CG-029、CG-036、CG-040、AD-054
- **设计映射**:第 25.1、25.4 章
- **修改范围**:`frontend/src/components/SecuritySettings.vue`、新增安全子组件和测试
- **实施步骤**:拆分登录密码、密保问题、离线恢复码、WebAuthn 安全密钥、外部安全邮箱管理和登录会话;实现外部邮箱绑定、验证、更换、删除、脱敏状态和近期重新认证交互;超级管理员不显示恢复码管理入口和恢复码首次提示,密码区域只显示“必须通过部署端重置服务开启专用通道”的中文说明,不提供或调用任何 Web 改密和密码恢复入口;验证码功能关闭时展示受控停用状态,但页面和后端功能仍须完成本轮实现与验收。
- **安全要求**:敏感操作前重新认证;恢复码明文不持久化;安全密钥操作不允许管理员代办。
- **测试要求**:每个子页面的成功、取消、过期、权限、Session 撤销和错误提示测试;覆盖外部邮箱绑定、验证、更换、删除、发送和脱敏状态;验证验证码默认关闭时不存在可用发送或恢复入口,启用并配置有效时完整流程可用。
- **验收标准**:管理员和普通用户可管理自己的密码、密保、恢复码、WebAuthn 和会话;超级管理员只能在 Web 管理自己的 WebAuthn 与会话,页面只展示部署端专用通道说明,不存在可调用的 Web 改密、恢复码或密码恢复入口;所有角色都不能访问其他用户安全凭据。
- **回退方式**:保留修改密码和退出功能,暂时关闭未完成子页面。
- **验收证据**:账户恢复页面和登录忘记密码弹窗已统一为单页面验证方式切换交互,详见 `frontend/src/views/RecoveryView.vue` 和 `frontend/src/views/LoginView.vue`;2026-08-27 `yarn.cmd build` 通过。账户安全完整功能和真实浏览器验收仍待后续任务。
### CG-044 实现登录后离线恢复码首次提示
- **状态**:未开始
- **优先级**:P0
- **依赖**:CG-034、CG-028、CG-043
- **设计映射**:第 18.3、25.4 章
- **修改范围**:登录后主布局、安全 Store、恢复码弹窗和测试
- **实施步骤**:管理员和普通用户读取后端 `showRecoverySetupPrompt`;登录后立即弹窗;支持立即生成或稍后处理;设置页持续显示风险状态;超级管理员固定不进入该恢复码引导,也不请求恢复码状态或生成接口。
- **安全要求**:是否提示由后端状态决定;关闭弹窗不能伪造“已配置”;每次新登录重新评估。
- **测试要求**:新管理员、新普通用户、超级管理员、已配置用户、稍后处理、重新登录、生成失败、多个标签页和角色差异测试;验证超级管理员页面不发起恢复码查询、生成或找回请求。
- **验收标准**:未配置恢复码的管理员和普通用户每次新登录第一时间看到提示,已配置用户不重复提示;超级管理员不显示恢复码提示、管理入口或 Web 找回入口,只能看到部署端专用重置通道说明。
- **回退方式**:保留账户安全页风险提示;不得伪造恢复码已配置状态。
- **验收证据**:待补充。
### CG-045 完成真实浏览器和可访问性验收
- **状态**:未开始
- **优先级**:P1
- **依赖**:CG-041、CG-042、CG-043、CG-044
- **设计映射**:第 25.6、29.4 章
- **修改范围**:前端样式、组件测试和验收记录
- **实施步骤**:在桌面、低高度和移动视口逐页验证;检查键盘、焦点、错误关联、滚动和横向溢出;验证 WebAuthn 不可用状态。
- **安全要求**:浏览器存储、控制台和网络日志不得出现 Secret、恢复码、Challenge 或票据。
- **测试要求**:至少覆盖超级管理员、管理员、普通用户和未登录状态;保存截图或 DOM 验证证据。
- **验收标准**:关键操作无遮挡、可键盘完成、错误提示清楚且无敏感信息泄露。
- **回退方式**:关闭未通过验收的页面入口,不影响已验证核心功能。
- **验收证据**:待补充。
### 第六阶段验收
- [ ] 前端只消费后端角色和能力;
- [ ] 配置页面支持验证、代次冲突、数据库名称迁移、审计、回滚和受控重启;
- [ ] 插件页面符合三级角色边界;
- [ ] 账户安全页面包含登录密码、密保问题、离线恢复码、WebAuthn、外部安全邮箱管理和登录会话分区;
- [ ] 首次登录恢复码提示符合要求;
- [ ] 桌面、低高度和移动视口验证通过。
---
## 10. 第七阶段:初始化、兼容切换和部署验证
### CG-046 实现 setupState 状态机和服务启动矩阵
- **状态**:未开始
- **优先级**:P0
- **依赖**:CG-010、CG-023
- **设计映射**:第 12 章
- **修改范围**:`backend/services/setup`、`backend/main.go`、HTTP 和邮件服务启动代码、测试
- **实施步骤**:实现 `new`、`bootstrap`、`ready`、`degraded`;建立合法转换;按状态启动受限服务;增加三数据库、主域名、SSL 和 HTTPS 切换完整预检。
- **安全要求**:无有效超级管理员、主域名或有效 SSL 不能进入 `ready`;配置损坏不得启动完整邮件服务;SSL 成功前 HTTP 只允许受控初始化范围,成功后生产管理后台强制 HTTPS;降级状态不回退公网明文管理。
- **测试要求**:所有状态转换、非法回退、服务矩阵、配置损坏、三种数据库失败、主域名和 SSL 未完成、HTTPS 切换及恢复测试。
- **验收标准**:每种状态只开放设计允许的服务,状态转换幂等并有审计。
- **回退方式**:停留 `bootstrap` 或 `degraded`,不强制写回 `isInit=true`。
- **验收证据**:待补充。
### CG-047 收敛初始化授权和首个超级管理员创建
- **状态**:未开始
- **优先级**:P0
- **依赖**:CG-046、CG-029
- **设计映射**:第 6.2、11.6、12.3 章
- **修改范围**:`backend/listen/http_server/setup_security.go`、Setup Controller、数据库初始化服务、SSL 初始化服务、前端初始化页和测试
- **实施步骤**:使用短期初始化授权并绑定来源和有效期;MySQL/PostgreSQL 只收集主机、用户名、密码及可选高级端口,SQLite 只选择类型;后端自动创建数据库和表结构;创建首个超级管理员;继续完成主域名和 SSL 双模式配置;全部成功后立即撤销匿名初始化能力。
- **安全要求**:初始化令牌不进入 URL 和日志;请求不接受数据库名称、表名、DSN、SQL、SQLite 路径或 SSL 服务器绝对路径;重复创建必须拒绝;只允许受控来源访问未初始化接口。
- **测试要求**:三数据库自动创建、权限不足、部分建库失败、令牌过期、重放、跨来源、并发创建、主域名和 SSL 校验、初始化完成后访问和请求体超限测试。
- **验收标准**:数据库和表由后端安全创建,首个账户固定为超级管理员,主域名和 SSL 完成后匿名初始化接口立即不可用且生产管理后台切换 HTTPS。
- **回退方式**:保持 `new` 状态并重新开始受控初始化,不手工写 `ready`。
- **验收证据**:待补充。
### CG-048 完成 V1 API 路由、兼容响应和废弃标记
- **状态**:未开始
- **优先级**:P1
- **依赖**:CG-013、CG-025、CG-038、CG-018
- **设计映射**:第 23、27 章
- **修改范围**:`backend/listen/http_server`、Controller、前端 API 封装和测试
- **实施步骤**:注册 `/api/v1`;拆分本人、跨用户、批量插件设置路由;增加配置审计筛选、详情和脱敏导出,配置回滚预览与执行,数据库名称迁移预览、创建和状态查询以及受控重启预览与执行;为 AD-048~AD-051 提供正式外部安全邮箱、验证码、登录二次验证和密码恢复路由的通用守卫与注册基础;为旧登录字段和只读响应提供短期兼容;对旧写接口设置停用计划和使用统计。
- **安全要求**:兼容层不能跳过新授权、严格解析、CSRF、Secret 处理或审计;冲突字段拒绝;数据库迁移接口只接收目标名称;重启接口不接受任意命令或服务名;验证码相关路由在完整实现和安全验收前保持关闭,但不得以关闭为由省略实现,也不得在校验成功前创建恢复票据。
- **测试要求**:新旧路由对照、本人接口不接受用户 ID、跨用户权限矩阵、批量和回滚预览票据、审计导出权限、数据库迁移参数白名单、固定服务重启、验证码功能关闭与受控启用、错误码、方法限制、请求大小和废弃告警测试。
- **验收标准**:前端全部使用 V1;旧接口即使保留也进入同一安全服务边界。
- **回退方式**:前端短期切回兼容路由,后端仍调用 V2 服务。
- **验收证据**:待补充。
### CG-049 实现受控功能开关和切换观测
- **状态**:未开始
- **优先级**:P1
- **依赖**:CG-048、CG-046
- **设计映射**:第 30.2 章
- **修改范围**:启动配置、服务装配、状态接口和测试
- **实施步骤**:实现六个迁移功能开关,包括默认关闭的 `external_email_recovery`;完整功能和安全验收通过后允许超级管理员受控启用;记录旧路径调用次数、错误率和切换状态;设置生产安全默认值。
- **安全要求**:开关不得禁用授权、凭据加密和恢复强因素;未知开关值拒绝启动或使用安全默认值。
- **测试要求**:全部组合的最低覆盖、错误值、热切换限制和生产默认值测试。
- **验收标准**:每个功能已完整实现后可按计划受控切换并有观测证据;默认关闭不代表延期实现,安全控制不存在关闭开关。
- **回退方式**:仅回退业务读写路径,不回退密码算法、Secret 加密和权限检查。
- **验收证据**:待补充。
### CG-050 停止旧配置、旧授权和插件 HTML 路径写入
- **状态**:未开始
- **优先级**:P1
- **依赖**:CG-049、CG-042
- **设计映射**:第 22.4、30 章
- **修改范围**:旧配置写接口、`SettingsHtml` 路由、`config.Instance` 写入点、兼容日志和测试
- **实施步骤**:统计调用归零;关闭旧写入;旧接口返回明确废弃错误或只读兼容;建立后续删除候选清单。
- **安全要求**:停止使用不等于删除文件;未经许可不删除旧路由文件、配置文件或数据库列。
- **测试要求**:代码搜索、运行时调用统计、旧接口写入拒绝、前端无调用和插件 HTML 隔离测试。
- **验收标准**:生产写路径只经过 ConfigManager、能力授权和 Schema 驱动插件设置。
- **回退方式**:仅在安全服务边界内重新开放兼容代理,不恢复旧直接写盘逻辑。
- **验收证据**:待补充。
### CG-051 完成 Windows、Ubuntu 和三数据库部署验证
- **状态**:未开始
- **优先级**:P0
- **依赖**:CG-047、CG-049、CG-050、AD-011、AD-015
- **设计映射**:第 24.4、30.4 章
- **修改范围**:构建配置、部署文档、平台测试和验收记录
- **实施步骤**:在 Windows 开发模式、Ubuntu 22.04、Ubuntu 24.04 验证;分别执行 MySQL、PostgreSQL、SQLite 自动初始化;验证 MySQL/PostgreSQL 数据库名称迁移;配置 Windows Service 和 systemd 固定服务重启适配器;检查文件权限和插件隔离。
- **安全要求**:生产插件隔离不足时拒绝插件启动;生产管理后台在 SSL 成功后强制 HTTPS;Web 进程不得执行客户端提交的命令或服务名;测试凭据全部为临时值。
- **测试要求**:启动、自动建库建表、数据库名称迁移成功和失败回退、登录、邮件协议、配置备份回滚、审计导出、受控重启、插件、完整邮箱验证码恢复流程和部署端专用重置通道测试。
- **验收标准**:六个目标环境组合有明确通过证据或阻塞说明,不以单平台成功代替全部兼容性。
- **回退方式**:回退应用版本和配置代次,保留新安全数据和迁移记录。
- **验收证据**:待补充。
### 第七阶段验收
- [ ] 四态初始化状态机和服务矩阵通过;
- [ ] 初始化自动建库建表、主域名、SSL、授权和首个超级管理员创建安全;
- [ ] 前端全部使用 V1 API;
- [ ] 功能开关不能关闭基础安全控制;
- [ ] 旧直接写入路径停止使用但未擅自删除;
- [ ] Windows、Ubuntu、三种数据库和固定服务重启验证完成。
---
## 11. 第八阶段:完整安全复审和验收
### CG-052 执行完整自动化回归和故障注入
- **状态**:未开始
- **优先级**:P0
- **依赖**:CG-051、AD-060、AD-061、AD-062、AD-063、AD-064
- **设计映射**:第 29 章
- **修改范围**:全部后端、前端、插件测试和验收记录
- **实施步骤**:运行 Go 完整测试、竞态测试、前端构建和测试、三个插件测试;执行配置事务、自动建库、数据库名称迁移、配置审计、受控重启、插件崩溃和超级管理员专用重置通道故障注入。
- **安全要求**:不得跳过失败测试;不得以重试成功掩盖不稳定;日志必须脱敏。
- **测试要求**:覆盖单元、集成、安全、浏览器和跨平台任务中规定的全部用例;超级管理员专用重置通道必须在 Windows、Ubuntu 22.04 和 Ubuntu 24.04 完成真实平台验证,不得只使用模拟实现替代。
- **验收标准**:所有目标测试通过;任何跳过项都有负责人、原因、风险和后续任务。
- **回退方式**:回退到最后一个完整通过的应用版本和配置代次。
- **验收证据**:待补充。
### CG-053 复审配置、Secret、迁移和回滚安全
- **状态**:未开始
- **优先级**:P0
- **依赖**:CG-052
- **设计映射**:第 6~11、28.1 章
- **修改范围**:`backend/config`、`backend/utils/credential`、配置 API 和审计
- **实施步骤**:审查唯一磁盘入口、结构化三数据库配置、严格 JSON、路径安全、代次、事务、7 天/30 天/4 份备份、回滚、数据库名称迁移、完整配置审计、受控重启、连接测试和 Secret 生命周期。
- **安全要求**:重点验证旧算法回退、明文落盘、日志泄露、SSRF、符号链接、审计删除和泄密、迁移越界、重启命令注入及崩溃混合代次漏洞不存在。
- **测试要求**:使用恶意夹具和故障注入复现每个风险点,检查 API、文件、日志和内存暴露边界。
- **验收标准**:无 P0/P1 配置安全问题;P2 问题有明确整改任务和风险接受人。
- **回退方式**:关闭配置写接口,使用最近有效配置只读运行或进入降级模式。
- **验收证据**:待补充。
### CG-054 复审角色、登录、密码和恢复流程安全
- **状态**:未开始
- **优先级**:P0
- **依赖**:CG-052
- **设计映射**:第 13~20、28.2 章
- **修改范围**:授权、认证、Session、恢复服务、用户 API 和本地维护通道
- **实施步骤**:审查三级角色、对象级授权、双标识解析、四通道认证、密码算法、固定密保答案规范化、恢复码、WebAuthn、重置票据、分角色跨用户凭据撤销、部署端专用重置服务,以及完整邮箱验证码、SMTP 投递、登录二次验证、外部邮箱恢复、管理页面、运营数据和定期清理。
- **安全要求**:重点验证防枚举、限流绕过、邮箱验证码启停状态的恢复降级、并发双花、WebAuthn 重放、最后超级管理员、超级管理员 Web 改密绕过、TCP 网络暴露、本机 IPC 权限、维护会话重放和跨进程复用、通道超时、管理进程退出以及开发模式自动开放。
- **测试要求**:完成正向矩阵和攻击矩阵;检查角色重置矩阵;检查超级管理员所有 Web 改密与恢复路径均被拒绝;检查普通 Web API、插件、配置和环境变量不能开启专用通道;检查 Named Pipe 和 Unix Socket 权限;检查密码不能通过参数、标准输入输出、环境变量、文件或日志泄漏;检查重置后安全凭据和票据均失效;检查邮箱验证码默认关闭时不能绕过强验证、受控启用后完整流程可用且验证码不持久化。
- **验收标准**:无可直接接管账户、提权、绕过强恢复凭据或远程开启超级管理员重置通道的路径;专用重置通道实现和跨平台安全验证未完成时不得通过复审。
- **回退方式**:关闭忘记密码和高风险管理入口,保留正常登录;专用重置通道存在安全问题时必须完全关闭,不得用普通 Web 恢复替代。
- **验收证据**:待补充。
### CG-055 复审插件源码、配置和运行隔离
- **状态**:未开始
- **优先级**:P0
- **依赖**:CG-052
- **设计映射**:第 21~22、28.3 章
- **修改范围**:`plugins`、`backend/services/plugin`、`backend/hooks` 和插件 API
- **实施步骤**:逐个审查三个插件源码;检查旧 PMail 依赖、磁盘读取、数据库 Secret、裁剪 RPC、强制网络白名单、Web Push、用户映射、Hook 生命周期和异常隔离。
- **安全要求**:插件不得读取主配置、DSN、主数据库、其他插件数据或主加密密钥;不得通过 HTML 设置页影响主页面;网络不能跳过主机、端口和协议白名单;管理员不得启停插件或重启未授权实例;批量用户配置只允许超级管理员按已确认预览执行。
- **测试要求**:恶意插件、配置和 Secret 泄露、SSRF、DNS 重绑定、跨白名单重定向、私网访问、Web Push 越权、超时、超限、崩溃、重复 Hook、越权重启、本人和跨用户设置混用、批量目标篡改、预览票据重放、越权用户设置和沙箱不可用测试。
- **验收标准**:单插件被攻破时不能直接获得主配置和数据库凭据,其他服务保持可用。
- **回退方式**:禁用风险插件,不关闭核心邮件服务。
- **验收证据**:待补充。
### CG-056 复审 API、前端和浏览器数据泄露
- **状态**:未开始
- **优先级**:P0
- **依赖**:CG-052
- **设计映射**:第 23、25~28 章
- **修改范围**:HTTP 路由、Controller、响应、前端 Store、页面和浏览器验收记录
- **实施步骤**:审查权限、CSRF、同源、请求大小、错误脱敏、缓存头、浏览器存储、控制台、网络日志、配置审计页面、数据库迁移、受控重启、登录邮箱二次验证、外部邮箱密码恢复、外部邮箱管理页面和 iframe 隔离。
- **安全要求**:前端隐藏不能代替授权;恢复码和 Secret 不得进入持久化存储;审计差异和导出必须脱敏;验证码关闭时不得显示可用恢复路径;SSL 成功后生产必须 HTTPS。
- **测试要求**:IDOR、CSRF、跨源、响应缓存、DOM 注入、审计导出泄密、回滚票据重放、数据库迁移参数注入、重启命令注入、验证码降级绕过、错误回显、浏览器历史和开发工具存储检查。
- **验收标准**:API 和浏览器中无明显敏感信息泄露、越权或弱化恢复路径。
- **回退方式**:关闭风险页面和写接口,保留安全只读状态页。
- **验收证据**:待补充。
### CG-057 完成最终验收、任务状态和遗留风险登记
- **状态**:未开始
- **优先级**:P0
- **依赖**:CG-053、CG-054、CG-055、CG-056、AD-066
- **设计映射**:第 29.5、31.4 章
- **修改范围**:本任务清单、安全审查报告和发布说明
- **实施步骤**:复核 57 项任务;更新每项状态和证据;登记未完成项;确认无 P0/P1 漏洞;形成是否允许发布的结论。
- **安全要求**:不得把“代码已写”当作安全完成;不得隐藏失败测试、未验证平台或已知风险。
- **测试要求**:抽查任务证据可重复;复跑关键安全测试;检查 Git 差异中无真实凭据和意外文件删除。
- **验收标准**:所有发布阻塞项已完成;任务状态准确;遗留风险有责任人、期限和接受结论。
- **回退方式**:结论为不允许发布,继续整改;不通过修改文档状态掩盖问题。
- **验收证据**:待补充。
### 第八阶段验收
- [ ] 完整自动化、故障注入和跨平台测试通过;
- [ ] 配置和 Secret 无 P0/P1 风险;
- [ ] 认证和恢复无账户接管或提权路径;
- [ ] 三个插件源码和运行隔离通过复审;
- [ ] API 和浏览器无明显敏感信息泄露;
- [ ] 57 项任务状态和证据准确。
---
## 12. 关键依赖链
```text
CG-001
├── CG-003 → CG-023 → CG-024 → CG-025
├── CG-005 → CG-006 → CG-007
│ └→ CG-010 → CG-011 → CG-012
├── CG-002 → CG-008 → CG-009 → CG-010
└── CG-004
CG-010 → CG-014 → CG-015 / CG-022
CG-008 + CG-016 + CG-002 → CG-017 → CG-018
CG-018 → CG-019 / CG-020 / CG-021
CG-023 → CG-024
CG-024 + CG-017 → CG-025
CG-023 + CG-026 → CG-027 → CG-028 / CG-029
CG-029 → AD-016 → AD-017
AD-015 + AD-016 → AD-017 → AD-018 → AD-021 → CG-030
AD-006~AD-020 + AD-062 + AD-063 → CG-031
CG-032 → CG-033 / CG-034 / CG-036
CG-034 → CG-035
CG-033 + CG-036 → CG-037
CG-033 + CG-035 + CG-037 → CG-038 → CG-039
CG-022 → AD-032~AD-038
CG-027~CG-028 → AD-039~AD-042
CG-038~CG-039 → AD-043~AD-047
后端服务完成 → CG-040 → CG-041 / CG-042 / CG-043
CG-043 + CG-034 → CG-044 → CG-045
CG-046 + CG-048 → CG-049 → CG-050
AD-011 + AD-015 + CG-050 → CG-051
AD-060~AD-064 + CG-051 → CG-052 → CG-053 / CG-054 / CG-055 / CG-056
CG-053~CG-056 → AD-066 → CG-057
```
---
## 13. 每轮实施记录模板
每次开始一组任务时追加记录,不得覆盖历史记录:
```text
日期:
执行任务:
开始状态:
修改文件:
实施摘要:
测试命令:
测试结果:
安全检查:
遗留问题:
回退验证:
结束状态:进行中 / 待复审 / 已完成 / 阻塞
复审人:
```
---
## 2026-08-27 CG-002 实施记录
- **日期**:2026-08-27
- **执行任务**:CG-002 建立敏感字段和安全能力清单
- **开始状态**:未开始
- **修改文件**:`backend/config/sensitive.go`、`backend/config/sensitive_test.go`、`backend/services/access/authorize.go`、`backend/services/access/capability.go`、`backend/services/access/catalog.go`、`backend/services/access/access_test.go`、`backend/services/access/matrix_test.go`、`backend/controllers/config.go`、`backend/controllers/config_error_test.go`、`backend/listen/http_server/http_server.go`、`backend/listen/http_server/config_route_test.go`
- **实施摘要**:扩展敏感字段目录,明确四类持久化策略和公共脱敏能力;补充配置、审计和回滚 API 的能力映射;恢复配置分区 `PUT` 路由;统一配置授权错误的稳定错误码并避免回显内部错误文本;补充配置路由、能力目录、角色恢复码和敏感响应测试。
- **测试命令**:`go test ./services/access ./config ./controllers ./listen/http_server`、`go test ./...`、`go vet ./...`、`git diff --check`
- **测试结果**:定向测试和全量测试通过;`go vet ./...` 通过;`git diff --check` 未发现空白错误。
- **安全检查**:默认拒绝未登记能力;管理员和普通用户执行受保护操作时要求有效恢复码;超级管理员按已确认边界豁免恢复码前置条件;错误响应不泄露内部错误文本和敏感字段;配置备份使用回滚能力而非普通读取能力。
- **遗留问题**:真实 Ubuntu、Windows、三数据库、多实例、生产日志/指标/追踪/缓存/队列/错误报告哨兵和最终发布验收尚未完成。
- **回退验证**:未改变旧配置读取路径;如需回退,可关闭新增配置管理能力并保留拒绝日志,不删除既有配置或数据。
- **结束状态**:待复审
- **复审人**:
---
## 2026-08-27 CG-003 实施记录
- **日期**:2026-08-27
- **执行任务**:CG-003 引入显式数据库迁移框架
- **开始状态**:未开始
- **修改文件**:`backend/db/migration/dialect.go`、`backend/db/migration/migration.go`、`backend/db/migration/registry.go`、`backend/db/migration/runner.go`、`backend/db/migration/schema.go`、相关测试文件、`backend/db/init.go`、`backend/db/init_migration_test.go`
- **实施摘要**:建立显式迁移注册表和连续版本校验;为 SQLite、MySQL、PostgreSQL 提供方言 SQL 或自定义迁移;记录迁移版本、名称、校验和、执行时间和耗时;增加数据库级并发锁、事务执行、失败回滚、重复执行跳过、未知版本拒绝和当前版本查询;生产环境不再默认依赖无版本 `Sync2`,兼容模式仅在显式配置并满足开发或测试条件时启用;补充默认迁移注册表的连续性和三数据库方言完整性测试。
- **测试命令**:`go test ./db/migration ./db`、`go test ./db/migration -run 'Test(Default|SQLite|Normalize|Runner|Unknown|Legacy|Custom)' -count=1`、`go test ./...`、`go vet ./...`、`git diff --check`
- **测试结果**:迁移专项测试和 `db` 测试通过;新增默认迁移连续性、名称和三数据库方言覆盖测试通过。MySQL/PostgreSQL 集成测试通过环境变量启用,当前环境未配置 `SMAIL_TEST_MYSQL_DSN` 和 `SMAIL_TEST_POSTGRES_DSN`,因此按测试设计跳过;不能据此宣称 MySQL/PostgreSQL 真实环境已验收。
- **安全检查**:迁移定义必须从版本 1 开始且连续;已应用迁移的名称或校验和变化会被拒绝;并发启动使用数据库锁;失败迁移不会写入完成记录;错误包装不输出迁移 SQL 中的 Secret;生产环境拒绝旧 `Sync2` 兼容模式;测试夹具不包含真实密钥。
- **遗留问题**:真实 MySQL、PostgreSQL、Ubuntu、Windows、多实例并发和生产部署仍未完成;CG-004 测试基线、跨平台故障注入和最终发布验收仍待后续任务;不应将本条状态视为三数据库或生产发布通过。
- **回退验证**:保留显式 `SMAIL_ENABLE_LEGACY_SYNC2` 兼容开关,不删除既有表和旧数据;生产环境仍拒绝该兼容模式,回退不得绕过版本迁移审计。
- **结束状态**:待复审
- **复审人**:
---
## 2026-08-27 CG-004 实施记录
- **日期**:2026-08-27
- **执行任务**:CG-004 建立配置重构测试基线
- **开始状态**:未开始
- **修改文件**:`docs/配置系统重构测试基线.md`、`docs/配置系统重构实施任务清单.md`
- **实施摘要**:建立后端 Go 全量测试、数据库迁移专项、静态检查、前端构建、数据库集成、浏览器验收和跨平台验收分类;定义 Windows PowerShell、Ubuntu 和三数据库的可重复命令;约束测试 DSN 只能通过临时环境变量注入;明确真实密钥、生产数据库和已有私钥、可执行文件不得作为测试输入。
- **测试命令**:`go test ./... -count=1`、`go vet ./...`、`go test ./db/migration ./db -count=1`、`yarn.cmd build`、`git diff --check`
- **测试结果**:后端全量测试通过;`go vet ./...` 通过;数据库迁移专项和 `db` 测试通过;前端 Vite 生产构建通过,仅有资源分块偏大的提示;MySQL/PostgreSQL 因未配置 `SMAIL_TEST_MYSQL_DSN` 和 `SMAIL_TEST_POSTGRES_DSN` 未执行真实集成测试,并已在基线文档中标记为未验证。
- **安全检查**:基线文档不包含真实凭据;测试使用临时目录或测试数据库;没有把跳过的集成测试写成通过;明确生产平台、真实 SMTP、多实例和生产观测不属于本机自动化结果。
- **遗留问题**:Ubuntu 22.04/24.04、Windows 生产服务、真实 MySQL/PostgreSQL、SMTP、多实例、浏览器和生产观测仍需独立环境验收;前端当前只有构建基线,未替代真实浏览器验收。
- **回退验证**:本任务仅新增中文测试基线文档,不改变生产代码、配置读取路径、数据库结构、私钥、可执行文件或旧测试配置。
- **结束状态**:待复审
- **复审人**:
---
## 14. 任务状态变更记录
| 日期 | 任务 | 原状态 | 新状态 | 说明 |
|---|---|---|---|---|
| 2026-08-28 | CG-009 | 未开始 | 已完成,等待复审 | 使用 `atomic.Pointer` 和 CAS 发布不可变运行时快照;补齐深拷贝、旧代次拒绝、并发读取/发布和 ConfigManager 返回值隔离测试;配置包竞态测试通过;真实生产进程切换和跨平台部署仍待验收 |
| 2026-08-28 | CG-009 | 已完成,等待复审 | 复审通过 | 独立复审确认 `atomic.Pointer` CAS 发布、深复制边界、旧代次冲突保护、返回值隔离和配置包竞态测试;`go test ./... -count=1`、`go vet ./...`、`git diff --check` 通过;仅本机自动化复审通过,真实生产进程切换、Ubuntu/Windows 部署及长期观测仍未覆盖 |
| 2026-08-28 | CG-008 | 已完成,等待复审 | 复审通过 | 复核插件 Secret 的 keep 保留、replace 加密、clear 确认、非法路径和直接密文拒绝逻辑;配置、控制器全量测试和 `go vet` 均通过,临时文件定向清理验证通过;真实数据库、SMTP、插件沙箱、Ubuntu/Windows 和生产环境边界继续保留为未验收项 |
| 2026-08-28 | CG-008 | 未开始 | 已完成,等待复审 | 完成统一 SecretChange 与 CredentialVault 适配;数据库、SMTP Relay 和插件 Secret 使用统一加密、版本、脱敏和更新语义;补齐插件 Secret 的 keep/replace/clear、非法路径与公共响应脱敏测试;Makefile 增加仅清理 `backend/.codex-smail-*` 的测试收尾逻辑;真实数据库、SMTP、插件沙箱、Ubuntu/Windows 和生产环境仍待集成验收 |
| 2026-08-27 | CG-005 | 未开始 | 已完成,等待复审 | 完成配置模型、三数据库条件字段、默认端口、SQLite `localRef` 约束和固定分区映射测试;自动化验证通过,真实数据库集成、跨平台部署和启动流程仍待验收 |
| 2026-08-27 | CG-002 | 未开始 | 已完成,等待复审 | 完成敏感字段目录、持久化策略、管理 API 能力映射、配置 PUT 路由和授权负向测试;自动化检查通过,真实平台和生产观测仍待验收 |
| 2026-08-27 | CG-003 | 未开始 | 已完成,等待复审 | 完成显式迁移框架、版本和校验和校验、三数据库方言定义、数据库锁、事务回滚和生产 `Sync2` 兼容边界;SQLite 自动化测试通过,MySQL/PostgreSQL 因未配置 DSN 未执行真实集成验收 |
| 2026-08-27 | CG-004 | 未开始 | 已完成,等待复审 | 建立 Go、迁移、vet、前端构建、数据库集成、浏览器和跨平台测试基线;本机自动化通过,真实三数据库和生产平台仍未验证 |
| 2026-08-25 | 全部编码任务 | 无 | 未开始 | 创建实施任务清单,尚未开始编码实施 |
| 2026-08-25 | CG-001 | 未开始 | 待复审 | 已完成首轮产品决定同步,继续根据后续确认修订验收边界 |
| 2026-08-25 | CG-001 | 待复审 | 已完成 | 需求升级为 0.7、独立需求升级为 0.3、技术设计升级为 0.5;完整验证码范围、`systemctl start smail-admin`、角色矩阵和跨文档依赖复审通过 |
| 2026-08-25 | CG-001 | 已完成 | 已完成 | 二次复审清理正文残留的验证码预留范围,明确仅内存验证码与非敏感运营数据边界,并补齐 CG-032、CG-048 到 AD 子任务的依赖 |
---
## 15. 发布阻塞条件
出现以下任一情况,不允许将本轮重构标记为完成或进入生产发布:
1. 存在未关闭的 P0 或 P1 安全漏洞;
2. 配置文件仍可能明文保存数据库、SMTP 或插件 Secret;
3. 仍存在通过旧算法或弱恢复方式绕过验证的路径;
4. 用户名和完整邮箱在不同协议中的认证结果不一致;
5. 管理员或普通用户可以越权修改不允许的插件配置;
6. 恢复码可以重复查看、重复使用或并发双花;
7. WebAuthn 未完整校验 Challenge、Origin、RP ID、签名和用户归属;
8. 超级管理员密码恢复能力可通过 TCP、普通 Web 页面或公共 API 访问;
9. 插件可以读取主配置、数据库 DSN、主数据库或其他插件配置;
10. 配置事务中断后可能以混合代次启动;
11. 前端、日志、审计或错误响应泄露 Secret、恢复码或票据;
12. 测试失败、跳过项或未验证平台没有明确记录;
13. 未经用户许可删除了文件、旧配置或数据库列;
14. 超级管理员可以通过 Web 修改或恢复自己的密码;
15. 普通用户可以访问含目标用户 ID 的跨用户插件设置接口;
16. 批量插件设置可以跳过预览、重放预览票据或静默覆盖用户个性化配置;
17. 管理员可以启停插件或重启未明确授权的插件实例;
18. 超级管理员本地维护会话可以重复使用、跨进程复用或从参数、环境变量、日志和长期配置中获得;
19. 外部安全邮箱验证码关闭、未通过安全验收或配置无效时仍可以形成可用恢复路径;
20. 超级管理员重置密码后目标用户的旧 WebAuthn、恢复码、Session、恢复流程或票据仍然有效;
21. 数据库名称迁移可以跨类型、跨服务器、跨账户执行,失败后切断旧数据库,或自动删除旧数据库;
22. 配置审计可被普通 Web API 删除、保留不足 365 天、导出未脱敏或导出行为未审计;
23. Web 重启接口可以接收或执行客户端提交的命令、脚本、参数或服务名;
24. 插件 Secret 明文进入文件、日志、审计或配置备份,或主加密密钥与密文存放在同一数据库;
25. 插件可绕过目标主机、端口和协议白名单,或未经能力授权使用 Web Push;
26. 超级管理员部署端固定重置服务、专用重置通道、Windows Named Pipe、Unix Domain Socket 平台适配器或相关安全测试未完成;
27. 完整邮箱验证码服务、SMTP 投递、登录邮箱二次验证、外部邮箱密码恢复、外部邮箱管理页面、运营数据或每 14 天定期清理任一项未完成;
28. Linux 正式入口不是唯一的 `systemctl start smail-admin`,或密码可经参数、标准输入输出、环境变量、文件、服务名或日志传递;
29. 密码重置权限不符合“超级管理员重置管理员和普通用户、管理员重置普通用户、普通用户仅重置本人、部署端仅重置超级管理员自身”;
30. AD-066 尚未完成独立清单最终发布评审或未向 CG-057 提供聚合验收证据。
完成上述 57 项任务并通过 30 项发布阻塞条件检查后,才能将配置系统重构进入最终发布评审。
---
## 2026-08-28 CG-016~CG-021 插件配置链路实施记录
- **本轮状态**:`[✓] 复审通过`
- **涉及任务**:CG-016、CG-017、CG-018、CG-019、CG-020、CG-021。
- **修改文件**:`backend/plugins/catalog/catalog.go`、`backend/plugins/catalog/catalog_test.go`、`backend/hooks/framework/framework.go`、`backend/hooks/base.go`、`backend/hooks/base_test.go`、`backend/hooks/spam_block/`、`backend/hooks/wechat_push/`、`plugins/pmail_telegram_push/hook/`。
- **实施摘要**:补齐插件目录中的逻辑 ID、可执行文件、权限能力、握手能力和设置字段声明;插件启动握手严格校验 ID、协议版本、能力集合和设置字段集合;运行时配置增加非零配置代次,主程序只向已启用且能力匹配的插件下发专属配置;插件继续只从受控 Secret 服务取得自身密钥,并拒绝旧密钥字段、未知能力、未知设置和未授权网络目标。
- **测试命令**:`go test ./... -count=1`(`server`)、`go test ./... -count=1`(`plugins/pmail_telegram_push`)、`go test -race ./hooks/... ./plugins/catalog ./services/plugin -count=1`(`server`)、`go test -race ./hook -count=1`(`plugins/pmail_telegram_push`)、`go vet ./...`、`git diff --check`。
- **当前测试结果**:本轮 `server` 全量测试、Telegram 插件全量测试、服务端 `go vet ./...`、服务端插件配置链路竞态测试和 Telegram 插件竞态测试均通过;目录声明专项测试通过;`git diff --check` 通过。
- **安全检查**:新增代次为零拒绝、握手能力严格集合匹配、运行时配置只携带当前插件字段;未发现 Secret 进入错误信息的新增路径。
- **未完成验收**:真实 Ubuntu 22.04/24.04、Windows 生产插件隔离、真实 MySQL/PostgreSQL、真实浏览器、生产 SMTP/IMAP/POP3、多实例部署和长期日志观测仍未完成,不能据此视为最终发布验收通过。
- **回退验证**:未删除既有文件、配置或数据库;如复审不通过,可通过停用插件回退,不恢复复制完整主配置文件的旧路径。
- **复审人**:Codex(2026-08-28,本机自动化复审)
## 2026-08-29 本轮开发完成记录
- **状态**:`[x] 已完成,等待复审`
- **已完成内容**:完成插件用户设置服务与 V1 API 的当前用户绑定、版本并发控制、未知字段拒绝和 Secret 不回显验证;完成插件运行时设置下发边界和 V1 插件页面安全头修正;清理前端对旧版插件配置保存接口的调用路径。
- **本地验证**:服务端全量测试通过,插件配置服务、控制器、框架和 HTTP 路由相关专项测试通过。
- **未完成真实验收**:真实 MySQL/PostgreSQL 配置迁移、Ubuntu/Windows 正式部署、插件生产隔离、浏览器页面、SMTP/IMAP/POP3 和 Telegram Bot 仍需现场复审。
- **复审日期**:2026-08-29(本机自动化复审)。
## 2026-08-30 配置审计、受控重启和数据库迁移基础链路复审记录
- **本轮状态**:`[x] 已完成,等待复审`
- **执行任务**:继续实施 CG-013,补齐配置审计详情与正式导出、受控重启预览、数据库名称迁移安全基础链路及定向测试。
- **修改文件**:`backend/config/audit_query.go`、`backend/config/audit_export.go`、`backend/config/audit_query_test.go`、`backend/config/audit_store.go`、`backend/controllers/config_audit.go`、`backend/controllers/config_audit_query_test.go`、`backend/controllers/database_migration.go`、`backend/controllers/restart.go`、`backend/listen/http_server/http_server.go`、`backend/listen/http_server/api_v1_compat.go`、`backend/listen/http_server/api_v1_compat_test.go`、`backend/services/access/catalog.go`、`backend/services/dbmigration/`、`backend/services/restart/`。
- **实施摘要**:配置审计事件支持稳定 ID、详情查询和正式 JSON/CSV 导出;导出响应设置禁止缓存并保留敏感字段脱敏边界;受控重启预览只返回固定 Smail 目标,不接受服务名、命令、脚本或参数;数据库迁移仅允许同类型、同服务器、同端口、同账户下的数据库名称或 SQLite 本地引用变更,采用短期一次性预览票据和按迁移 ID 隔离的状态机,失败时保留旧配置。
- **定向测试**:`go test ./services/dbmigration -count=1`、`go test -race ./services/dbmigration -count=1`、`go test ./config -count=1`、`go test ./controllers ./services/restart ./listen/http_server -count=1` 均通过。
- **安全检查**:修复迁移状态读取的并发访问边界;拒绝状态倒退;票据只保存哈希且执行后立即失效;审计详情和导出不返回密码、密钥、票据或底层错误;新路由已纳入能力目录和方法限制测试。
- **明确未完成项**:真实 MySQL、PostgreSQL、SQLite 数据复制、校验和原子切换执行器尚未接入;Ubuntu 22.04、Windows、真实三数据库、多实例、浏览器和生产环境尚未完成实机验收;CG-013 不得标记为最终复审通过,数据库迁移相关任务继续保持 `[~] 进行中`。
- **全量复审状态**:待执行 Go 全量测试、`go vet`、前端构建与 ESLint、差异和敏感信息检查。
- **Git 状态**:本轮不自动提交、不自动推送,等待用户明确授权。
- **复审人**:待复审。
## 2026-08-30 全量自动化复审结果
- **复审状态**:`[x] 已完成,等待人工与实机复审`
- **Go 测试**:`go test ./... -count=1` 通过;`go test -race ./... -count=1` 通过;`go vet ./...` 通过。
- **前端检查**:`npm.cmd run build` 通过;ESLint 通过。构建仅提示既有资源分块偏大和动态导入提示,不影响构建成功。
- **仓库检查**:`git diff --check` 通过;未发现新增 `` `n ``、`` `r`n ``、替换字符或 HTML 数字实体乱码;未发现本轮测试生成的服务二进制进入 Git 状态。
- **结论**:本轮配置审计、受控重启预览、数据库迁移安全基础链路和定向测试达到待复审状态;配置系统重构整体仍不能宣称全部完成。
- **发布阻塞**:真实 MySQL/PostgreSQL/SQLite 数据复制、校验、原子切换执行器尚未实现;真实 Ubuntu 22.04、Windows、浏览器、三数据库、邮件投递、多实例和生产环境验收尚未完成;CG-013 及依赖真实迁移执行器的任务不得标记为 `[✓]`。
- **Git 操作**:没有执行 `git add`、`git commit` 或 `git push`;既有工作区改动和未跟踪文件保持原样,等待用户授权后再按文件范围提交。
- **复审人**:待人工复审。
## 2026-08-30 回滚票据并发与失败重试实施记录
- **本轮状态**:`[x] 已完成,等待复审`
- **执行任务**:继续实施配置系统回滚票据的并发消费、临时失败重试和稳定错误映射。
- **开始状态**:配置回滚票据已具备操作者绑定和成功后失效能力,但临时失败会提前消耗票据,并发执行状态缺少明确错误边界。
- **修改文件**:`backend/config/manager.go`、`backend/config/manager_v2.go`、`backend/config/manager_v2_test.go`、`backend/controllers/config_error.go`、`backend/controllers/config_error_test.go`。
- **实施摘要**:增加票据 `InFlight` 状态;在回滚执行前原子标记执行中,避免并发重复消费;对上下文取消和运行时快照暂不可用保留票据并允许在有效期内重试;通过已应用标志区分审计失败与未提交失败;新增 `CONFIG_ROLLBACK_IN_PROGRESS` 中文错误响应。
- **测试命令**:`go test ./config ./controllers -run 'Test(ConfigManagerRollbackTicket|ConfigErrorDetailsMapsRollbackInProgress)' -count=1`、`go test ./... -count=1 -timeout 30m`、`go vet ./...`、`git diff --check`。
- **测试结果**:配置管理器回滚票据专项测试通过;服务端全量测试通过;`go vet ./...` 和差异检查通过;前端 ESLint、生产构建已在上一轮复核通过。
- **安全检查**:票据不落盘、不回显;错误响应使用稳定中文信息;会话绑定、过期清理和成功后单次消费语义保持不变。
- **遗留问题**:CG-013 依赖的真实三数据库复制、校验、原子切换执行器尚未接入;跨平台、真实浏览器、邮件投递、多实例和生产验收仍开放,不能标记配置系统整体完成。
- **回退验证**:只新增回滚票据状态和错误映射,未删除既有配置管理路径;可通过回退提交 `acf0322` 恢复上一版本。
- **结束状态**:待复审
- **复审人**:待人工复审。
---
## 2026-08-30 配置快照发布失败重试整改记录
- **本轮状态**:`[x] 已完成,等待复审`
- **实施内容**:统一配置启动加载、配置应用、配置回滚、数据库切换和插件 Secret 迁移的运行时快照发布入口;当磁盘事务已成功提交但运行时快照暂不可用时,保留可重试状态并将配置服务标记为降级。
- **接口提示**:新增稳定错误码 `CONFIG_RUNTIME_SNAPSHOT_UNAVAILABLE`,返回 HTTP 503,并明确提示配置已保存、运行时尚未切换,可稍后重试应用。
- **新增测试**:覆盖应用阶段快照发布失败后的磁盘代次、运行时旧快照、降级状态和再次应用成功;保留回滚票据失败重试及并发保护测试。
- **验证结果**:服务端 `go test ./... -count=1 -timeout 30m` 和 `go vet ./...` 通过;未将真实 MySQL、PostgreSQL、Ubuntu、Windows、浏览器和生产部署验收标记为完成。
- **遗留边界**:事务提交后快照发布失败的跨进程恢复仍依赖服务重载或后续重试;真实多数据库复制、校验、原子切换和部署联调继续按实机清单验收。
## 2026-08-31 全量代码状态复核
> 本节是 2026-08-31 对当前实现的增量状态口径。原任务条目中的旧状态保留为实施历史;以下状态优先用于判断当前代码完成度,但不能替代真实平台和生产发布验收。
| 任务范围 | 当前状态 | 复核结论 |
|---|---|---|
| CG-001 | `[✓] 复审通过` | 需求、边界和依赖关系已经冻结。 |
| CG-002~CG-007 | `[x] 已完成,等待复审` | 敏感字段、显式迁移、测试基线、配置模型、严格解析和验证器均已实现。 |
| CG-008~CG-009 | `[✓] 复审通过` | CredentialVault 和不可变运行时快照已有测试证据。 |
| CG-010~CG-014 | `[x] 已完成,等待复审` | ConfigManager、事务恢复、备份回滚、状态/审计/受控重启、旧配置迁移均已有实现和自动化测试。 |
| CG-015 | `[x] 已完成,等待实机复审` | SSL 分区和受控存储已实现;真实证书、Nginx 和平台权限仍需验收。 |
| CG-016~CG-021 | `[✓] 复审通过` | 插件目录、授权、专属配置下发和三个插件源码整改已有本机自动化复审证据。 |
| CG-022~CG-044 | `[x] 已完成,等待复审` | SMTP/邮箱策略、三级角色、统一认证、密码、部署端重置、恢复仓储、密保、恢复码、WebAuthn、恢复状态机、API 和前端页面均已有实现。 |
| CG-045 | `[!] 暂缓或存在阻塞` | 真实浏览器三角色、可访问性和完整交互流程尚未人工验收。 |
| CG-046~CG-050 | `[x] 已完成,等待部署复审` | setupState、初始化授权、V1 兼容、功能开关和旧写路径收敛已有代码和测试。 |
| CG-051 | `[!] 暂缓或存在阻塞` | Windows、Ubuntu、MySQL、PostgreSQL 和 SQLite 真实部署矩阵尚未全部完成。 |
| CG-052~CG-055 | `[x] 已完成,等待独立复审` | 自动化回归、故障路径以及配置、认证、插件安全审查已形成代码和测试证据。 |
| CG-056~CG-057 | `[!] 暂缓或存在阻塞` | 浏览器数据泄露复审和最终发布验收依赖真实环境、人工交互及生产安全评审。 |
### 过时记录修正
旧记录中“真实数据库复制执行器尚未接入”的结论已经过时。当前已存在 `backend/services/dbmigration/sql_executor.go`、`sqlite_executor.go`、运行时执行器工厂、复制校验、配置切换和相关测试。该修正只表示代码已接入,不表示真实 MySQL/PostgreSQL 数据复制、失败回滚和原子切换已经实机通过。
### 当前实现证据
- 配置核心:`backend/config/model.go`、`parser.go`、`validator.go`、`secret.go`、`snapshot.go`、`manager.go`、`manager_v2.go`、`transaction.go`、`storage.go`。
- 备份、审计和迁移:`backend/config/manager_backups.go`、`audit_store.go`、`audit_query.go`、`database_migration.go`。
- 数据库复制与切换:`backend/services/dbmigration/service.go`、`sql_executor.go`、`sqlite_executor.go`。
- 受控重启和接口:`backend/services/restart`、`backend/controllers/config.go`、`config_audit.go`、`database_migration.go`、`restart.go`。
- 自动化复核:服务端全量测试、竞态检测、`go vet`、前端 ESLint 和生产构建在本轮最终提交前统一执行并记录。
### 发布结论
配置系统重构的工作区代码已进入待复审状态,但 CG-045、CG-051、CG-056 和 CG-057 仍受真实浏览器、跨平台、三数据库、多实例和生产发布评审阻塞。不得将“代码完成”表述为“生产验收完成”。
## 2026-08-31 数据库迁移执行器入口与结构校验整改记录
- **关联任务**:CG-003、CG-051、CG-052~CG-055。
- **本轮状态**:`[x] 已完成,等待复审`。
- **实施内容**:统一 `SQLExecutor` 与 `SQLCopier` 的数据库复制请求校验;直接调用复制器时也会拒绝无效数据库配置、类型不一致、非法库名、同名目标库和跨连接目标,避免绕过服务层产生不安全 SQL 操作。
- **结构校验**:MySQL 复制完成后复核源库和目标库的表集合、表列顺序、列名、类型、可空性、默认值、额外属性和键属性;PostgreSQL 复制完成后复核表集合以及列定义,再逐表复核行数。
- **自动化测试**:新增入口校验、危险库名、同名库、跨主机、类型不支持和表集合精确比较测试;`go test ./services/dbmigration -count=1` 通过。
- **安全检查**:库名仍仅允许安全标识符;数据库名称只通过驱动参数或安全引用进入 SQL;未新增 HTTP 重置入口、未放宽凭据存储、未删除任何数据文件。
- **跨平台或数据库覆盖**:当前为代码级和 SQLite 测试环境验证;真实 MySQL、PostgreSQL、Ubuntu、Windows、生产权限和故障恢复仍需实机复审。
- **遗留问题**:真实三数据库复制、权限差异、超大库耗时、网络中断后的生产回滚和原子切换尚未完成实机验收。
- **结束状态**:待复审。
- **复审人**:待人工复审。
## 2026-08-31 MySQL 外键结构最终校验补强记录
- **关联任务**:CG-003、CG-051、CG-052~CG-055。
- **本轮状态**:`[x] 已完成,等待真实数据库与部署复审`。
- **实施内容**:MySQL 结构化复制器在复制外键后,重新读取源库和目标库的外键元数据并进行精确集合比较;同时保留安全库名、同类型、同连接和目标库名称校验。
- **校验字段**:比较表名、约束名、外键列顺序、引用 schema、引用表、引用列顺序、`ON UPDATE` 和 `ON DELETE` 规则;源库内部 schema 会映射为目标库 schema 后再比较。
- **自动化验证**:新增外键等价比较和差异拒绝测试;`go test ./... -count=1 -timeout 30m`、`go test -race ./... -count=1 -timeout 45m`、`go vet ./...`、前端 ESLint 和生产构建均通过。
- **发布边界**:真实 MySQL/PostgreSQL/SQLite 迁移、跨平台部署、Nginx、浏览器、邮件系统、多实例和生产故障恢复仍待实机复审;CG-051、CG-056、CG-057 不升级为最终复审通过。
- **复审日期**:2026-08-31(本机自动化复审)。
## 2026-09-01 Windows 部署脚本兼容性复核记录
- **关联任务**:CG-031、CG-051~CG-057。
- **本轮状态**:`[x] 已完成,等待 Windows 实机复审`。
- **实施内容**:修复 Windows PowerShell 5.1 的 UTF-8 中文脚本解析兼容性、安装脚本 `PackageRoot` 参数绑定问题,并确保 `Smail` 服务创建和 SID 类型设置完成后再应用服务 ACL;新增静态顺序和脚本编码回归检查。
- **自动化验证**:`go test ./cmd/smail-admin -count=1 -v`、`go test ./... -count=1 -timeout 30m`、`go vet ./...`、前端生产构建、ESLint 和 `git diff --check` 均通过。
- **发布边界**:真实 Windows 管理员安装、Ubuntu systemd、三数据库、SMTP、浏览器三角色、多实例和最终安全评审仍未完成,CG-045、CG-051、CG-056、CG-057 不升级为最终复审通过。
- **复审日期**:2026-09-01(本机自动化复核)。