# Scert 开发任务清单 ## 当前开发批次(2026-09-28,先开发后统一测试) - [x] 生命周期前后端收尾、七个资源读取入口隔离及绑定写入授权已有源码,等待统一测试。 - [x] 按多对多补齐共享服务器、局部清空、去重、审计失败保留和路径冲突保护及回归源码;页面使用悬浮提示,未执行测试或构建。 - [~] 继续其他业务资源写入与任务授权整改;服务器别名与在途部署路径占用仍待补齐,不算本批已完成。 - [!] 历史正式包与回归不能用于新代码验收;准确范围见任务执行清单首节、模型第十一/十二节和支持矩阵第二十六节。 以下为历史正式包和浏览器批次。 ## 当前正式包与浏览器批次(2026-09-28 20:15) - [x] 干净提交 `5f9af32` 的 Windows 正式发布包构建成功;发布清单、压缩包内容和实际运行的前后端文件核对一致,主程序已实际启动。 - [x] 临时 HTTPS 身份核验以及浏览器未认证、无效令牌拒绝路径已验证;首次初始化后端专项 128 个叶子通过、4 条平台条件跳过,退出 0。 - [!] 当前浏览器文件工具的工作区范围不包含 Scert,尚未传入本机一次性地址并兑换会话;未绕过限制,未进行初始化后的成员页面验收。 - [ ] 合法初始化、项目成员页面和权限布局验证继续保留;项目增删改、全部资源与排队任务权限及生产门禁仍未完成。 原始 44 项状态保持不变,精确证据与限制见支持矩阵第二十五节;以下为各自时间点的历史批次。 ## 历史项目入口批次(2026-09-28 19:54) - [x] 可见项目分页接口、管理员和普通项目管理员入口、独立成员页面、账户 ID 与禁止缓存保护已实现。 - [x] 前端 198 项通过;最后源码后端专项 83 个叶子通过、4 条条件跳过,完整后端 1700 个叶子通过、54 条条件跳过;双版本 MySQL 三轮组合各 195 个叶子通过,静态检查、模块校验及双平台构建通过。 - [x] 三轮专项竞态 249 个叶子通过、12 条外部 MySQL 条件跳过,退出码 0;已同步对应任务和验证文档。完整命令、证据和边界见支持矩阵第二十四节,当前任务以执行清单首节为准,提交状态以 Git 记录为准。 - [ ] 真实浏览器、项目增删改、所有资源和排队任务权限、PostgreSQL 当前实库、Linux 原生及生产验收。 原始 44 项范围不缩减、总状态不升级。下方均为按当时源码记录的历史批次,其中成员页面和项目入口未交付的描述已被本节取代。 > 最新批次(2026-09-28 19:10):成员列表账户分页、授予/撤销接口、应用接线与失败审计已实现;修复审计错误误报 409,并补充验证会话认证后撤权/停用、请求取消、审计存储故障和 DELETE 输入拒绝。当前专项、双版本 MySQL 三轮、完整后端 1679 个叶子与双平台构建通过;成员三轮竞态 186 个叶子通过、9 条外部 MySQL 条件跳过,退出码 0。详细证据见支持矩阵第二十三节。成员页面、项目入口及完整资源/任务授权仍待完成,原始 44 项总状态不升级。下方各批次均为历史记录。 > 当前批次(2026-09-28):成功成员变更与审计同事务写入已实现,审计失败回滚;源码检查点不是正式发布。SQLite 候选为 v1.59.0,最后源码取消查询/WAL 专项、完整后端、双版本 MySQL 三轮组合及双平台构建通过;原 MySQL 索引异常根因未关闭。最新任务状态、最终竞态和证据见执行清单首节与支持矩阵第二十二节,不复用旧批次数字。下一开发重点为成员 Web/API、分页、失败审计、业务资源入口与排队任务重新判权。 > 当前批次(模式 14):项目成员多角色、实时判权、同语句授予/撤销及三库迁移已实现,SQLite/MySQL 双版本与独立 Windows 程序成员备份恢复通过。后续仍需成员管理 Web/API 与审计、全部资源入口和排队任务重判;本批基础模块不等于业务隔离完成。最新证据见执行清单首节与支持矩阵第二十一节。原始 44 项不缩减,P0-05/P0-06/P0-07 继续 `[~]`;下方为历史记录。 > 当前批次(模式 13):任务/审计范围快照、历史保留与回填、实际任务关联和操作者来源已实现;新增尝试拒绝缺失资源、项目变更和未知父任务。详细状态与测试以《Scert整改任务执行清单》首节和支持矩阵第二十节为准。其他资源、成员授权和生产验收继续实施,P0-05/P0-06/P0-07 保持 `[~]`,全部 44 项不缩减。下方各段保留历史证据,不表示最新状态。 > 最新执行状态:`7284958` 已交付域名/服务器归属、绑定约束与三库模式 11;`92c844f` 新增模式 12 修复 SQLite 替换目标行绕过引用保护,完整后端、三次竞态、MySQL 双版本及 Windows 独立程序回归均已通过。下方“归属仍未实现”只描述项目根实体历史批次。任务、审计等剩余资源与项目成员权限仍待接入,P0-06/P0-07 继续 `[~]`;全部 44 项范围不变。精确状态见《Scert整改任务执行清单》,证据及条件跳过见支持矩阵第十九节。 > 2026 年 9 月 28 日当前进度:P0-06 项目根实体子项 `[x]`,已新增三库第 10 号迁移、默认项目、项目模型和仓储;SQLite、MySQL 5.7/8.0、竞态与后端全量测试,以及独立 Windows 程序项目备份恢复通过。资源归属字段、回填、引用保护及项目授权仍未实现,P0-06/P0-07 总项保持 `[~]`。新证据及命令见支持矩阵第十八节;旧模式 1~9 的历史证据不自动升级为模式 10 的全部数据库验收。 > 2026-09-27 任务规格:完整 44 项及六阶段验收规范见《整改任务规格与验收约定》和《Scert整改任务执行清单》。以下历史勾选不替代当前整改状态,不把旧测试结果当成新增需求已经实现。 > 当前进度(源码 `fd2810b`):P0-05 `[~]`。已复现并修复 SQLite 历史模式 1~3 有任务数据时升级到迁移 4 失败的问题;模式 1~9 的带数据升级、依赖对象保留及失败重试已有回归。本批干净提交构建的独立 Windows 程序完成历史模式 3 备份、升级、恢复后再次升级,以及升级后备份恢复。SQLite 专项通过 71 个叶子用例,27 个升级/恢复用例连续 3 次竞态检测通过,详见《构建版本与数据库支持矩阵》第十七节。旧发行包真实数据迁移、完整发行包安装、真实服务重启、Linux 原生执行、取消边界及其余数据库和生产门禁仍未完成;全部 44 项范围不变。 > 2026-09-27 范围调整:本文件保留早期开发历史,当前执行以《Scert整改合并优化清单》和《Scert整改任务执行清单》为准。正式交付仅为 Web 和 Windows/Linux 服务端;本文件中的 Wails 桌面窗口、托盘、桌面更新、桌面配置和桌面 UI 测试均退出正式开发及验收范围,不再作为未完成交付项。CLI 限定为初始化及服务运维,不另建业务管理界面。 > 同日 CLI 调整:下文 `domain`、`server`、`ssh-key`、`renew`、`deploy` 等业务命令及其测试结果仅为历史记录,当前正式入口已停用,请使用 Web;详见《命令行运维范围说明》。 > 2026-09-15 最新进展:见 [发布加固与实机验收记录](发布加固与实机验收记录.md)。初始化事务、远程部署锁、回滚与 SSH 安全依赖已加固;Linux 候选已构建并通过隔离实机推送验收。管理端仍未完成初始化,正式 ACME、业务 reload、TLS/SNI 和浏览器全流程继续标记 `[!]`,不是生产放行。 > 文档用途:作为 Scert 项目后续开发、进度跟踪、阶段复审和验收的执行清单。 > > 项目名称:Scert > 当前阶段:整改实施与分层验证 > > 文档状态:保留开发历史,当前进度由整改执行清单和分级规格统一跟踪 > > 编制日期:2026-08-25 > Git 远程名称:Scert > Git 远程地址:`https://git.pcux.cn/xuans/Scert.git` --- ## 一、任务状态说明 | 标记 | 含义 | |---|---| | `[ ]` | 未开始 | | `[~]` | 进行中 | | `[x]` | 已完成,等待复审 | | `[✓]` | 复审通过 | | `[!]` | 暂缓或存在阻塞 | 开发过程中,每个任务完成后先标记为 `[x]`,经过复审和验证后再标记为 `[✓]`。未经过验证的实现不得直接标记为复审通过。 --- ## 二、已确认的需求基线 ### 2.1 项目和平台 - [x] 项目名称为 `Scert`。 - [x] 支持 Windows 和 Linux。 - [x] 目标构建架构为 amd64。 - [x] 基础测试范围为 Windows 10/11、Ubuntu 22.04 + Nginx。 - [x] 扩展测试范围为 Ubuntu 24.04 + Nginx、CentOS/Rocky Linux、Debian、Caddy、Apache 和其他主流反向代理。 - [x] Linux systemd 以 Ubuntu 22.04 默认版本作为最低兼容基线。 - [x] 提供命令行版本、Web 管理界面和 Wails 桌面版。 - [x] CLI、Web 和桌面版共享同一套核心服务、配置和数据库。 ### 2.2 工具链基线 - [x] Go:`go1.26.2`。 - [x] Node.js:`v24.19.0`。 - [x] npm:`11.17.0`,Windows PowerShell 中优先使用 `npm.cmd`。 - [x] Wails:`v2.11.0`。 - [x] 编写代码时使用英文标识符。 - [x] 注释、说明、文档和界面显示使用中文。 ### 2.3 ACME 和证书 - [x] 第一阶段使用 Let’s Encrypt。 - [x] 使用 `go-acme/lego` 作为唯一 ACME 客户端实现。 - [x] 支持 Let’s Encrypt Production 和 Staging。 - [x] 支持 DNS-01 验证。 - [x] 第一阶段支持单域名、泛域名和多域名 SAN 证书。 - [x] SAN 证书以主域名作为管理归属。 - [x] 保存完整 SAN 域名集合。 - [x] SAN 集合变化时生成新的证书标识和证书版本。 - [x] 续期失败时保留原证书,避免服务中断。 ### 2.4 DNS 验证 第一阶段 DNS 验证适配范围: - [x] Cloudflare。 - [x] 阿里云 DNS。 - [x] DNSPod。 - [x] CNAME 委派。 - [x] 华为云。 - [x] 腾讯云。 - [x] AWS Route 53。 - [x] Google Cloud DNS。 - [x] 预留其他 DNS 服务商扩展接口。 ### 2.5 数据库 - [x] 支持 MySQL 5.7。 - [x] 支持 MySQL 8.0。 - [x] 支持 SQLite。 - [x] MySQL 5.7 作为基础开发和最低兼容版本。 - [x] MySQL 8.0 作为兼容性测试版本。 - [x] SQLite 用于单机、桌面版和开发测试模式。 - [x] 使用 `database/sql` 和 Repository 数据访问层。 - [x] MySQL 与 SQLite 分别维护迁移脚本和方言适配。 - [x] 不通过 PATH 中的单个 `mysql` 命令判断版本。 本机 MySQL 客户端版本记录: | 安装路径 | 版本 | 用途 | |---|---|---| | `E:\DB\5.7\bin\mysql.exe` | MySQL 5.7.44 | 基础开发和最低兼容性验证 | | `E:\DB\8.0\bin\mysql.exe` | MySQL 8.0.45 | 兼容性测试 | ### 2.6 HTTPS 模式 - [x] 默认模式:核心服务直接终止 HTTPS。 - [x] 高级模式:Nginx/Caddy 终止公网 HTTPS,核心服务使用内部 HTTPS。 - [x] 初始化期间允许 HTTP。 - [x] 初始化完成后管理后台强制使用 HTTPS。 ### 2.7 通知边界 - [x] 支持 HTTP API 通知。 - [x] 支持 SMTP 出站客户端通知。 - [x] Scert 不实现 SMTP、IMAP、POP3 邮件服务器端。 - [x] SMTP、IMAP、POP3 协议表仅作为外部邮件服务兼容性参考。 - [x] HTTP 通知支持自定义地址、Bearer Token、HMAC-SHA256、无认证、详细事件、统一事件、自定义请求头、完整部署明细、证书序列号、管理后台链接、2xx 成功判断和可配置重试。 ### 2.8 默认目录 Linux: ```text 证书:/ssl 安装:/scert 配置:/scert/conf 日志:/scert/log 备份:/scert/backups ``` Windows: ```text 证书:{安装目录}\Scert\ssl 数据库:{安装目录}\Scert\data 配置:{安装目录}\Scert\config 日志:{安装目录}\Scert\logs 备份:{安装目录}\Scert\backups ``` --- ## 三、开发原则和边界 - [ ] 不在第一轮基础骨架中虚构证书申请已经完成。 - [ ] 不在未完成验证前宣称 DNS Provider 已经可用。 - [ ] 不在未完成远程测试前宣称多服务器部署完成。 - [ ] 所有长任务使用持久化任务记录。 - [ ] 所有证书操作保留审计日志。 - [ ] 所有敏感信息必须加密保存或脱敏处理。 - [ ] 续期和部署失败时保留旧证书。 - [ ] 安装、升级和卸载不得删除用户证书、数据库和备份。 - [ ] 远程命令必须经过白名单或严格格式校验。 - [ ] 不把用户输入直接拼接为 Shell 命令。 - [ ] 不把数据库连接信息、Token、密码和私钥写入 Git。 - [ ] 不未经用户同意删除任何文件。 - [ ] 不未经用户明确要求提交或推送 Git。 --- ## 四、阶段总览 | 阶段 | 名称 | 主要目标 | 状态 | |---|---|---|---| | 0 | 需求和架构冻结 | 锁定开发基线和边界 | `[~]` | | 1 | 项目基础工程 | 建立可编译、可运行的 Go 工程 | `[ ]` | | 2 | 配置系统 | 完成跨平台配置和默认目录 | `[ ]` | | 3 | 日志和错误 | 建立日志、错误和审计基础设施 | `[ ]` | | 4 | 数据库 | 完成 MySQL/SQLite 连接、迁移和模型 | `[ ]` | | 5 | 安全权限 | 完成管理员认证、角色和敏感信息保护 | `[ ]` | | 6 | 域名证书模型 | 完成域名、SAN、证书版本模型 | `[ ]` | | 7 | ACME/DNS | 集成 lego 和 DNS-01 Provider | `[ ]` | | 8 | 自动续期 | 完成调度器、任务状态机和失败恢复 | `[ ]` | | 9 | 多服务器部署 | 完成 SSH/SFTP、reload、回滚和验证 | `[ ]` | | 10 | Web 服务 | 完成 HTTP/HTTPS API 和部署校验 | `[ ]` | | 11 | 通知系统 | 完成 HTTP API 和 SMTP 出站通知 | `[ ]` | | 12 | Web 管理后台 | 完成管理页面和初始化向导 | `[ ]` | | 13 | CLI | 完成初始化、域名、续期、部署和查询命令 | `[ ]` | | 14 | Wails 桌面版 | 完成桌面封装和托盘能力 | `[ ]` | | 15 | 平台安装 | 完成 Windows Service、systemd 和安装包 | `[ ]` | | 16 | 测试 | 完成单元、集成、安全和兼容性测试 | `[ ]` | | 17 | 发布验收 | 完成构建、发布和概要验收 | `[ ]` | --- ## 五、阶段 0:需求和架构冻结 ### 5.1 文档基线 - [x] 需求确认文档已经生成。 - [x] 技术架构设计文档已经生成。 - [x] 已确认使用 `go-acme/lego`。 - [x] 已确认 SAN 纳入第一阶段。 - [x] 已确认双 HTTPS 模式。 - [x] 已确认 MySQL 5.7、MySQL 8.0 和 SQLite。 - [x] 已确认 HTTP 通知接口的 12 项要求。 - [x] 已确认 DNS Provider 第一阶段清单。 - [ ] 将需求编号与代码模块建立对应关系。 - [ ] 将暂缓事项和阶段外事项建立清单。 ### 5.2 阶段 0 交付物 - [x] `SSL服务程序需求确认文档.md` - [x] `SSL服务程序技术架构设计文档.md` - [ ] `Scert开发任务清单.md` - [ ] 需求编号与模块映射表 - [ ] 第一阶段范围说明 阶段验收标准: - 需求文档、技术架构文档和任务清单没有互相矛盾的基础决策。 - 代码开发统一使用已确认的 `go-acme/lego` 方案。 - MySQL 5.7 和 MySQL 8.0 的用途明确区分。 --- ## 六、阶段 1:项目基础工程 ### 6.1 目录结构 - [ ] 创建 `backend` Go 后端目录。 - [ ] 创建 CLI 入口目录。 - [ ] 创建内部业务模块目录。 - [ ] 创建数据库迁移目录。 - [ ] 创建测试目录。 - [ ] 完善 `frontend` 前端目录。 - [ ] 创建 `desktop` Wails 封装目录。 - [ ] 创建基础开发说明。 建议结构: ```text Scert/ ├── backend/ │ ├── cmd/scert/ │ ├── internal/ │ │ ├── app/ │ │ ├── config/ │ │ ├── database/ │ │ ├── domain/ │ │ ├── repository/ │ │ ├── service/ │ │ ├── httpapi/ │ │ ├── notifier/ │ │ ├── acme/ │ │ ├── deploy/ │ │ ├── scheduler/ │ │ ├── security/ │ │ └── platform/ │ ├── migrations/mysql/ │ ├── migrations/sqlite/ │ ├── tests/ │ └── go.mod ├── frontend/ ├── desktop/ ├── scripts/ ├── doc/ └── README.md ``` ### 6.2 Go 模块和依赖 - [ ] 创建 `go.mod`。 - [ ] 确定 Go Module 路径。 - [ ] 设置 Go 版本。 - [ ] 引入 `go-sql-driver/mysql`。 - [ ] 引入 `modernc.org/sqlite`。 - [ ] 引入 Web 框架。 - [ ] 引入 CLI 框架。 - [ ] 引入 `go-acme/lego`。 - [ ] 引入安全密码哈希依赖。 - [ ] 执行依赖整理和版本锁定。 - [ ] 检查依赖许可证和安全公告。 ### 6.3 首个可运行入口 - [ ] 实现 `scert version`。 - [ ] 实现 `scert help`。 - [ ] 实现 `scert serve`。 - [ ] 实现启动参数解析。 - [ ] 实现配置文件路径参数。 - [ ] 实现监听地址参数。 - [ ] 实现数据库驱动参数。 - [ ] 实现优雅退出。 - [ ] 实现启动失败的中文错误提示。 阶段验收标准: ```text scert version 可以执行 scert help 可以显示中文帮助 scert serve 可以启动服务 Windows amd64 可以编译 Linux amd64 可以交叉编译 Ctrl+C 可以优雅退出 ``` --- ## 七、阶段 2:配置系统 ### 7.1 配置模型 - [ ] 服务配置。 - [ ] 数据库配置。 - [ ] 证书存储配置。 - [ ] 日志配置。 - [ ] HTTPS 配置。 - [ ] ACME 配置。 - [ ] DNS Provider 配置。 - [ ] SMTP 配置。 - [ ] HTTP 通知配置。 - [ ] 安全配置。 - [ ] 平台运行配置。 ### 7.2 默认目录 - [ ] 实现 Linux 默认目录。 - [ ] 实现 Windows 默认目录。 - [ ] 支持用户自定义证书根路径。 - [ ] 支持用户自定义安装目录。 - [ ] 支持配置文件覆盖默认路径。 - [ ] 支持环境变量覆盖配置。 - [ ] 支持命令行参数覆盖配置。 - [ ] 检查目录权限。 - [ ] 自动创建必要目录。 - [ ] 禁止初始化流程覆盖已有证书。 ### 7.3 配置读写和升级 - [ ] 实现配置文件读取。 - [ ] 实现配置文件保存。 - [ ] 实现配置字段校验。 - [ ] 实现配置版本字段。 - [ ] 实现配置升级机制。 - [ ] 实现配置备份。 - [ ] 实现配置恢复。 - [ ] 敏感字段单独加密保存。 - [ ] 敏感字段不写入普通日志。 --- ## 八、阶段 3:日志、错误和审计 ### 8.1 日志系统 - [ ] 使用结构化日志。 - [ ] 支持日志级别。 - [ ] 支持控制台输出。 - [ ] 支持文件输出。 - [ ] 支持日志轮转。 - [ ] 支持任务日志。 - [ ] 支持错误日志。 - [ ] 支持审计日志。 - [ ] 记录请求 ID。 - [ ] 记录任务 ID。 - [ ] 记录操作用户。 - [ ] 对密码、Token、密钥和私钥进行脱敏。 ### 8.2 错误模型 - [ ] 定义配置错误。 - [ ] 定义数据库错误。 - [ ] 定义 ACME 错误。 - [ ] 定义 DNS 错误。 - [ ] 定义部署错误。 - [ ] 定义证书校验错误。 - [ ] 定义通知错误。 - [ ] 定义权限错误。 - [ ] 定义未知错误。 - [ ] 统一 CLI、Web 和任务日志的错误分类。 --- ## 九、阶段 4:数据库和数据模型 ### 9.1 数据库连接层 - [ ] 实现数据库驱动选择。 - [ ] 实现 SQLite 连接。 - [ ] 实现 MySQL 5.7 连接。 - [ ] 实现 MySQL 8.0 连接。 - [ ] 实现连接池配置。 - [ ] 实现连接健康检查。 - [ ] 实现连接关闭。 - [ ] 实现数据库错误分类。 - [ ] DSN 日志脱敏。 - [ ] 使用明确端口和 DSN 区分两套 MySQL。 ### 9.2 数据库方言适配 - [ ] 处理自增主键差异。 - [ ] 处理布尔字段差异。 - [ ] 处理时间字段差异。 - [ ] 处理 JSON 字段差异。 - [ ] 处理分页语句差异。 - [ ] 处理事务差异。 - [ ] 处理索引差异。 - [ ] 处理唯一约束差异。 - [ ] SQLite 启用 WAL 和 busy timeout。 - [ ] MySQL 使用连接池和事务隔离。 ### 9.3 第一版数据表 - [ ] `users` - [ ] `roles` - [ ] `user_roles` - [ ] `domains` - [ ] `domain_identifiers` - [ ] `certificates` - [ ] `certificate_versions` - [ ] `dns_providers` - [ ] `dns_credentials` - [ ] `servers` - [ ] `domain_servers` - [ ] `deployment_records` - [ ] `tasks` - [ ] `task_attempts` - [ ] `notification_channels` - [ ] `notification_deliveries` - [ ] `audit_logs` - [ ] `settings` - [ ] `schema_migrations` ### 9.4 数据库迁移 - [ ] 建立 MySQL 迁移目录。 - [ ] 建立 SQLite 迁移目录。 - [ ] 实现迁移版本表。 - [ ] 实现迁移执行器。 - [ ] 实现重复执行保护。 - [ ] 实现迁移失败处理。 - [ ] 实现启动时迁移。 - [ ] 实现迁移状态查询。 - [ ] 测试 MySQL 5.7 迁移。 - [ ] 测试 MySQL 8.0 迁移。 - [ ] 测试 SQLite 迁移。 --- ## 十、阶段 5:安全和权限 ### 10.1 管理员认证 - [ ] 管理员账号创建。 - [ ] 管理员密码设置。 - [ ] bcrypt 或等效安全哈希。 - [ ] 登录失败限制。 - [ ] 会话创建。 - [ ] 会话过期。 - [ ] 退出登录。 - [ ] CSRF 防护。 - [ ] Secure Cookie。 - [ ] HttpOnly Cookie。 - [ ] SameSite Cookie。 ### 10.2 角色权限 - [ ] 超级管理员。 - [ ] 管理员。 - [ ] 普通用户。 - [ ] 域名级权限。 - [ ] 服务器级权限。 - [ ] 证书上传权限。 - [ ] 续期权限。 - [ ] 部署权限。 - [ ] 配置查看权限。 - [ ] 敏感配置隐藏。 ### 10.3 敏感信息保护 - [ ] DNS API 凭据加密存储。 - [ ] SSH 私钥加密存储。 - [ ] SMTP 密码加密存储。 - [ ] HTTP Token 加密存储。 - [ ] HMAC 密钥加密存储。 - [ ] 生成配置主密钥。 - [ ] 配置主密钥备份。 - [ ] 配置主密钥恢复。 - [ ] 私钥文件权限设置为 600 或 Windows 等效安全权限。 --- ## 十一、阶段 6:域名、SAN 和证书模型 ### 11.1 域名管理 - [x] 添加域名。 - [x] 编辑域名。 - [x] 删除域名。 - [x] 启用或禁用自动续期。 - [x] 配置生产或开发环境。 - [x] 配置单域名证书。 - [x] 配置泛域名证书。 - [x] 配置 SAN 证书。 - [ ] 配置关联服务器。 - [x] 保存 DNS Provider 标识,为后续 Provider 接入预留。 - [ ] 配置 CNAME 委派详细参数。 - [x] 校验 FQDN。 - [x] 检查域名重复。 - [x] 检查泛域名格式。 - [x] 检查 SAN 域名集合。 ### 11.2 SAN 管理 - [x] 定义主域名。 - [x] 定义 SAN 域名集合。 - [ ] 保存 SAN 集合快照。 - [ ] 生成证书标识。 - [ ] SAN 集合变化时生成新的证书标识。 - [ ] 不覆盖旧 SAN 证书。 - [x] SAN 域名去重。 - [x] SAN 域名合法性校验。 - [x] 申请前展示 SAN 集合预览。 - [ ] 保存 SAN 部署明细。 ### 11.3 证书文件管理 - [ ] 生产证书目录。 - [ ] 开发证书目录。 - [ ] 单域名目录。 - [ ] 泛域名目录。 - [ ] SAN 证书目录。 - [ ] `current` 目录。 - [ ] `versions` 历史目录。 - [ ] 证书链保存。 - [ ] 私钥保存。 - [ ] 证书元数据保存。 - [ ] 证书序列号保存。 - [ ] 证书指纹保存。 - [ ] 证书有效期保存。 - [ ] 私钥权限设置。 - [ ] 证书版本清理策略。 --- ## 十二、阶段 7:ACME 和 DNS 验证 ### 12.1 Lego 基础集成 - [ ] 引入 `go-acme/lego`。 - [ ] 实现 ACME Client 创建。 - [ ] 配置 Let’s Encrypt Staging。 - [ ] 配置 Let’s Encrypt Production。 - [ ] 配置 ACME 账号邮箱。 - [ ] 保存 ACME 账号信息。 - [ ] 保存 ACME 注册状态。 - [ ] 实现 ACME Order。 - [ ] 实现证书申请。 - [ ] 实现证书续期。 - [ ] 实现证书撤销。 - [ ] 实现 ACME 错误分类。 - [ ] 实现速率限制提示。 ### 12.2 DNS Provider 接口 - [ ] 定义 DNS Provider 接口。 - [ ] 定义凭据验证接口。 - [ ] 定义 Zone 查询接口。 - [ ] 定义 TXT 记录创建接口。 - [ ] 定义 TXT 记录删除接口。 - [ ] 定义传播检测接口。 - [ ] 定义权限检测接口。 - [ ] 定义 Provider 配置模型。 - [ ] 定义 Provider 错误模型。 ### 12.3 第一批 DNS 实现 - [ ] Cloudflare。 - [ ] 阿里云 DNS。 - [ ] DNSPod。 - [ ] 华为云。 - [ ] 腾讯云。 - [ ] AWS Route 53。 - [ ] Google Cloud DNS。 - [ ] CNAME 委派。 - [ ] 其他服务商扩展占位。 ### 12.4 CNAME 委派 - [ ] 配置专用验证域。 - [ ] 生成 `_acme-challenge` 目标记录。 - [ ] 自动创建 CNAME。 - [ ] 检查 CNAME 是否生效。 - [ ] 自动创建失败时提示用户。 - [ ] 支持用户手动确认 CNAME。 - [ ] 清理临时记录。 - [ ] 记录委派操作日志。 --- ## 十三、阶段 8:自动续期调度 ### 13.1 调度器 - [ ] 实现持久化调度器。 - [ ] 每日检查证书状态。 - [ ] 证书剩余 6 天或更少时触发续期。 - [ ] 支持自定义检查周期。 - [ ] 支持手动触发续期。 - [ ] 支持任务取消。 - [ ] 支持任务暂停。 - [ ] 支持任务恢复。 - [ ] 支持任务优先级。 ### 13.2 任务状态机 任务状态: ```text pending running succeeded failed error unknown cancelled rolled_back partial_success ``` - [ ] 定义任务状态。 - [ ] 定义任务阶段。 - [ ] 定义重试次数。 - [ ] 定义错误信息。 - [ ] 定义开始和结束时间。 - [ ] 定义操作者。 - [ ] 定义关联域名。 - [ ] 定义关联证书版本。 - [ ] 定义关联服务器。 - [ ] 实现任务幂等。 - [ ] 实现同域名任务互斥。 - [ ] 实现全局 ACME 任务限制。 - [ ] 实现失败恢复。 - [ ] 实现任务历史查询。 ### 13.3 续期流程 - [ ] 查询即将到期证书。 - [ ] 检查 DNS Provider。 - [ ] 创建 ACME Order。 - [ ] 执行 DNS-01。 - [ ] 获取证书。 - [ ] 校验证书链。 - [ ] 校验证书域名。 - [ ] 保存新证书版本。 - [ ] 更新 `current` 指向。 - [ ] 触发部署。 - [ ] 执行部署后验证。 - [ ] 发送成功通知。 - [ ] 失败时保留旧证书。 - [ ] 失败时发送通知。 --- ## 十四、阶段 9:多服务器部署 ### 14.1 服务器配置 - [ ] 添加服务器。 - [ ] 编辑服务器。 - [ ] 删除服务器。 - [ ] 配置服务器名称。 - [ ] 配置 IP 或主机名。 - [ ] 配置 SSH 端口。 - [ ] 配置 SSH 用户。 - [ ] 配置 SSH 私钥。 - [ ] 配置主机指纹。 - [ ] 配置证书目录。 - [ ] 配置私钥目录。 - [ ] 配置证书链目录。 - [ ] 配置 reload 命令。 - [ ] 配置 Web 服务类型。 ### 14.2 SSH/SFTP - [ ] 实现 SSH 密钥认证。 - [ ] 禁止密码登录。 - [ ] 实现主机指纹校验。 - [ ] 指纹变化时阻止部署。 - [ ] 实现 SSH 连接超时。 - [ ] 实现 SFTP 上传。 - [ ] 实现远程目录检查。 - [ ] 实现远程文件备份。 - [ ] 实现临时文件上传。 - [ ] 实现原子替换。 - [ ] 实现远程权限设置。 - [ ] 实现远程命令白名单。 ### 14.3 部署回滚 - [ ] 部署前备份远程旧证书。 - [ ] 上传证书文件。 - [ ] 上传私钥文件。 - [ ] 上传证书链文件。 - [ ] 执行 Web 服务 reload。 - [ ] reload 失败时回滚。 - [ ] 部署失败时保留旧文件。 - [ ] 每台服务器独立保存部署结果。 - [ ] 支持部分成功状态。 - [ ] 支持全部失败状态。 - [ ] 支持手动重新部署。 --- ## 十五、阶段 10:Web 服务和验证 ### 15.1 Web API - [ ] 创建 HTTP 服务。 - [ ] 创建 HTTPS 服务。 - [ ] 实现 HTTP 初始化模式。 - [ ] 实现 HTTPS 默认模式。 - [ ] 实现内部 HTTPS 高级模式。 - [ ] 实现健康检查接口。 - [ ] 实现版本接口。 - [ ] 实现统一 API 响应格式。 - [ ] 实现统一错误格式。 - [ ] 实现请求日志。 - [ ] 实现请求 ID。 - [ ] 实现基础限流。 ### 15.2 本地证书校验 - [ ] 检查证书文件存在。 - [ ] 检查私钥文件存在。 - [ ] 检查证书和私钥匹配。 - [ ] 检查证书链完整。 - [ ] 检查证书有效期。 - [ ] 检查证书域名匹配。 - [ ] 检查 SAN 集合。 - [ ] 检查证书序列号。 - [ ] 检查证书指纹。 ### 15.3 远程 HTTPS 校验 - [ ] 解析 A 记录。 - [ ] 解析 AAAA 记录。 - [ ] 对域名发起 HTTPS 请求。 - [ ] 校验远程证书链。 - [ ] 校验远程证书域名。 - [ ] 校验远程证书有效期。 - [ ] 校验证书序列号。 - [ ] 保存每个 IP 的校验结果。 - [ ] 校验失败时标记任务错误。 - [ ] 校验失败时发送通知。 --- ## 十六、阶段 11:通知系统 ### 16.1 HTTP API 通知 - [ ] 支持用户自定义请求地址。 - [ ] 支持 Bearer Token。 - [ ] 支持 HMAC-SHA256。 - [ ] 保留无认证模式。 - [ ] 支持详细事件。 - [ ] 支持统一事件。 - [ ] 默认使用详细事件。 - [ ] 请求字段统一使用英文。 - [ ] 支持自定义请求头。 - [ ] 支持完整服务器部署明细。 - [ ] 支持证书序列号。 - [ ] 支持管理后台链接。 - [ ] HTTP 200-299 判定成功。 - [ ] 默认请求超时 10 秒。 - [ ] 默认重试 3 次。 - [ ] 支持自定义重试次数和间隔。 - [ ] 支持 `request_id`。 - [ ] 实现接收方幂等要求说明。 - [ ] 敏感信息不写入日志。 ### 16.2 SMTP 出站通知 - [ ] 支持 SMTP 地址和端口。 - [ ] 支持账号和密码。 - [ ] 支持多个收件人。 - [ ] 支持明文连接限制。 - [ ] 支持 STARTTLS。 - [ ] 支持隐式 TLS。 - [ ] 发件人名称默认为 `Scert`。 - [ ] 发件人地址保留可配置。 - [ ] 邮件标题格式统一。 - [ ] 邮件正文包含任务结果。 - [ ] 支持成功、失败、错误、未知状态。 - [ ] 支持通知独立重试。 --- ## 十七、阶段 12:Web 管理后台 ### 17.1 初始化向导 - [ ] 检查是否首次运行。 - [ ] 配置管理后台域名。 - [ ] 配置管理员账号。 - [ ] 配置管理员密码。 - [ ] 配置邮件服务器。 - [ ] 配置收件人。 - [ ] 配置证书存储根路径。 - [ ] 至少配置一种 DNS 验证方式。 - [ ] 校验 DNS API 权限。 - [ ] 初始化数据库。 - [ ] 创建管理员账号。 - [ ] 申请管理后台证书。 - [ ] 部署管理后台证书。 - [ ] 切换 HTTPS。 - [ ] 记录初始化日志。 ### 17.2 管理页面 - [ ] 登录页面。 - [x] 首页仪表盘。 - [x] 域名列表页面。 - [x] 添加和编辑域名页面。 - [ ] 证书详情页面。 - [ ] SAN 域名管理页面。 - [ ] DNS Provider 配置页面。 - [ ] CNAME 委派配置页面。 - [ ] 服务器列表页面。 - [ ] 服务器部署状态页面。 - [ ] 手动续期页面。 - [ ] 手动部署页面。 - [ ] 任务列表和详情页面。 - [ ] 操作日志页面。 - [ ] 邮件通知配置页面。 - [ ] HTTP 通知配置页面。 - [ ] 系统配置页面。 - [ ] 备份恢复页面。 - [ ] 用户和角色页面。 ### 17.3 页面验收 - [x] 使用中文界面。 - [x] 适配桌面浏览器。 - [ ] 适配低高度窗口。 - [x] 适配移动视口基础布局。 - [x] 无严重横向溢出。 - [x] 错误提示清晰。 - [x] 危险操作二次确认。 - [ ] 敏感字段默认隐藏。 - [x] 任务状态可刷新。 --- ## 十八、阶段 13:CLI 命令 ### 18.1 初始化命令 - [ ] `scert init`。 - [ ] 交互式填写管理员账号。 - [ ] 交互式填写管理员密码。 - [ ] 交互式填写管理后台域名。 - [ ] 交互式填写邮件配置。 - [ ] 交互式填写证书根路径。 - [ ] 交互式选择 DNS Provider。 - [ ] 交互式填写 DNS 凭据。 - [ ] 测试 DNS 凭据。 - [ ] 初始化数据库。 - [ ] 申请和部署管理后台证书。 ### 18.2 域名和证书命令 - [x] `scert domain add`。 - [ ] `scert domain edit`。 - [x] `scert domain delete`。 - [x] `scert domain list`。 - [ ] `scert domain show`。 - [ ] `scert certificate list`。 - [ ] `scert certificate show`。 - [ ] `scert certificate upload`。 - [ ] `scert certificate validate`。 - [ ] `scert renew`。 - [ ] `scert deploy`。 ### 18.3 查询和配置命令 - [ ] `scert status`。 - [ ] `scert logs`。 - [ ] `scert config show`。 - [ ] `scert config set`。 - [ ] `scert config validate`。 - [ ] `scert backup`。 - [ ] `scert restore`。 - [ ] `scert version`。 - [ ] 支持非交互模式。 - [ ] 支持脚本退出码。 - [ ] 支持任务编号输出。 - [ ] 支持等待任务完成。 --- ## 十九、阶段 14:Wails 桌面版 - [ ] 创建 Wails 项目结构。 - [ ] 接入同一套 Vue 前端。 - [ ] 桌面端启动核心服务。 - [ ] 桌面端连接本地核心服务。 - [ ] 检查核心服务健康状态。 - [ ] 实现桌面端初始化页面。 - [ ] 实现系统托盘。 - [ ] 实现服务启动、停止和重启。 - [ ] 实现开机自启动配置。 - [ ] 实现桌面端日志查看。 - [ ] 实现桌面端错误提示。 - [ ] Windows 10 安装测试。 - [ ] Windows 11 安装测试。 - [ ] 桌面端与浏览器功能一致性测试。 - [ ] 卸载不删除用户证书和备份。 --- ## 二十、阶段 15:平台服务和安装 ### 20.1 Linux - [x] Linux 安装器创建 `Scert` 服务运行用户和同名用户组,并使用 `nologin` 禁止交互式登录。 - [x] 创建 `/scert`。 - [x] 创建 `/scert/conf`。 - [x] 创建 `/scert/data`。 - [x] 创建 `/scert/log`。 - [x] 创建 `/scert/backups`。 - [x] 创建默认 `/ssl`,并允许安装时指定其他安全绝对路径作为证书根目录。 - [x] 设置证书根目录所有权,由 `Scert` 服务用户和 root 管理。 - [~] 配置目录及现有敏感配置文件权限已收紧;真实 ACME 私钥文件 `0600` 仍需在证书申请模块和 Linux 实机中复审。 - [~] 已建立 `Scert` 用户与 root 的目录管理边界;证书上传、历史版本和部署文件的最终属主策略待证书模块复审。 - [x] 创建 `Scert.service` 和 `Scert-admin.service`。 - [x] 核心服务保留独立启停和开机启动能力;`Scert-admin` 不注册开机启动、不自动重启、不提供 reload,日常只提供 start 和 stop。 - [ ] Ubuntu 22.04 systemd 基线测试。 - [ ] Ubuntu 24.04 测试。 - [ ] Debian 测试。 - [ ] CentOS/Rocky Linux 测试。 ### 20.2 Windows - [ ] 支持选择自定义安装目录。 - [ ] 创建 `Scert\ssl`。 - [ ] 创建 `Scert\data`。 - [ ] 创建 `Scert\config`。 - [ ] 创建 `Scert\logs`。 - [ ] 创建 `Scert\backups`。 - [ ] 设置 Windows 文件权限。 - [ ] 创建 Windows Service。 - [ ] 配置服务启动、停止和重启。 - [ ] Windows 10 测试。 - [ ] Windows 11 测试。 - [ ] 升级不覆盖用户数据。 - [ ] 卸载不删除证书和备份。 --- ## 二十一、阶段 16:测试 ### 21.1 单元测试 - [ ] 配置读写测试。 - [ ] 配置校验测试。 - [ ] 路径处理测试。 - [ ] 数据库迁移测试。 - [ ] Repository 测试。 - [ ] 域名校验测试。 - [ ] SAN 集合测试。 - [ ] 证书解析测试。 - [ ] 证书链校验测试。 - [ ] 私钥匹配测试。 - [ ] 任务状态机测试。 - [ ] 重试策略测试。 - [ ] HMAC 签名测试。 - [ ] 通知请求构造测试。 - [ ] SSH 主机指纹测试。 - [ ] 部署回滚测试。 ### 21.2 数据库兼容性测试 - [ ] MySQL 5.7 建库和迁移。 - [ ] MySQL 5.7 CRUD 和事务。 - [ ] MySQL 8.0 建库和迁移。 - [ ] MySQL 8.0 CRUD 和事务。 - [ ] SQLite 建库和迁移。 - [ ] SQLite CRUD 和事务。 - [ ] SQLite 并发访问。 - [ ] SQLite WAL。 - [ ] SQLite 数据备份和恢复。 ### 21.3 集成测试 - [ ] 初始化完整流程。 - [ ] 添加域名流程。 - [ ] SAN 证书流程。 - [ ] Let’s Encrypt Staging 申请流程。 - [ ] DNS Provider 流程。 - [ ] CNAME 委派流程。 - [ ] 自动续期流程。 - [ ] 多服务器部署流程。 - [ ] 部署失败回滚流程。 - [ ] 远程 HTTPS 校验流程。 - [ ] HTTP 通知流程。 - [ ] SMTP 通知流程。 - [ ] CLI 与 Web 共用数据验证。 ### 21.4 安全测试 - [ ] 管理员密码不可明文存储。 - [ ] DNS 密钥不可明文输出。 - [ ] SSH 私钥不可明文输出。 - [ ] HTTP Token 不写入日志。 - [ ] HMAC 密钥不写入日志。 - [ ] 防止路径穿越。 - [ ] 防止命令注入。 - [ ] 防止未授权访问。 - [ ] 防止越权操作。 - [ ] 防止重复任务。 - [ ] 防止证书错误覆盖。 - [ ] 防止私钥权限过宽。 - [ ] 防止 HTTP 通知重放。 --- ## 二十二、阶段 17:构建、发布和最终验收 ### 22.1 构建任务 - [ ] Windows amd64 构建。 - [ ] Linux amd64 构建。 - [ ] 后端单文件构建。 - [ ] 前端生产构建。 - [ ] Wails 桌面版构建。 - [ ] 构建时注入版本信息。 - [ ] 统一构建产物命名。 - [ ] 生成构建产物校验和。 - [ ] 编写构建说明。 ### 22.2 发布文件 - [ ] Windows Service 安装包。 - [ ] Windows 桌面版安装包。 - [ ] Linux amd64 发布包。 - [ ] Linux systemd 服务文件。 - [ ] 默认配置模板。 - [ ] 数据库迁移文件。 - [ ] 升级说明。 - [ ] 回滚说明。 - [ ] 用户操作说明。 ### 22.3 最终验收 - [ ] Web 可以添加域名并申请证书。 - [ ] SAN 证书可以成功申请。 - [ ] 泛域名证书可以成功申请。 - [ ] 证书剩余 6 天时自动续期。 - [ ] 续期成功后部署到多台服务器。 - [ ] 部署后自动 reload Web 服务。 - [ ] 部署后远程 HTTPS 校验成功。 - [ ] 失败时保留原证书。 - [ ] 失败时发送通知。 - [ ] 用户证书可以上传和部署。 - [ ] CLI 与 Web 数据一致。 - [ ] Windows 10/11 可以运行。 - [ ] Ubuntu 22.04 + Nginx 可以运行。 - [ ] MySQL 5.7 可以运行。 - [ ] MySQL 8.0 兼容性测试通过。 - [ ] SQLite 单机模式可以运行。 - [ ] Wails 桌面版可以运行。 --- ## 二十三、首轮开发范围 首轮开发优先完成可运行的基础骨架,不直接进入完整证书申请和远程部署。 ### 首轮任务 - [✓] 创建 Go 模块。 - [✓] 创建 CLI 入口。 - [✓] 创建配置模型。 - [✓] 实现 SQLite 数据库连接。 - [✓] 实现 MySQL 数据库连接。 - [✓] 实现数据库迁移框架。 - [✓] 实现基础数据表。 - [✓] 实现日志系统。 - [✓] 实现 HTTP 服务。 - [✓] 实现 `/healthz` 健康检查接口。 - [✓] 实现 `/api/v1/status` 状态接口。 - [✓] 实现 `scert version`。 - [✓] 实现 `scert init` 基础配置初始化。 - [✓] 实现 `scert status` 基础状态查询。 - [✓] 编写配置、数据库、健康检查测试。 - [✓] 完成 Windows 编译和 Linux amd64 交叉编译。 ### 首轮验收目标 ```text scert version 可以执行 scert help 可以显示中文帮助 scert init 可以生成初始配置 scert status 可以显示服务状态 scert serve 可以启动服务 GET /healthz 返回成功 GET /api/v1/status 返回服务状态 SQLite 可以初始化和迁移 MySQL 5.7 可以连接和迁移 MySQL 8.0 可以连接和迁移 基础单元测试通过 Windows amd64 可以编译 Linux amd64 可以交叉编译 ``` ### 首轮暂不宣称完成 - [ ] ACME 证书申请。 - [ ] DNS Provider 实际调用。 - [ ] 自动续期。 - [ ] SSH/SFTP 远程部署。 - [ ] Nginx/Caddy/Apache 实际 reload。 - [ ] 完整 Web 管理界面。 - [ ] 完整 Wails 桌面版。 - [ ] Windows Service。 - [ ] Linux systemd。 --- ## 二十四、开发执行规则 - [ ] 每开始一个阶段,将阶段状态标记为 `[~]`。 - [ ] 阶段实现完成后,将任务标记为 `[x]`。 - [ ] 完成测试并等待复审后,才标记为 `[✓]`。 - [ ] 发现阻塞时标记为 `[!]`,并记录阻塞原因。 - [ ] 不把未测试功能标记为复审通过。 - [ ] 每个阶段完成后更新本文件。 - [ ] 每个阶段完成后执行格式化、编译和测试。 - [ ] 长时间任务每 5-10 分钟汇报一次进度。 - [ ] 不使用脚本批量替换中文内容。 - [ ] Git 提交信息使用中文。 - [ ] 未经用户明确要求不提交和推送。 - [ ] 不删除现有文件。 --- ## 二十五、当前进度 | 项目 | 状态 | |---|---| | 需求确认 | `[✓]` 复审通过 | | 技术架构确认 | `[✓]` 复审通过 | | 开发任务清单 | `[✓]` 已生成,等待复审 | | 项目代码开发 | `[~]` 进行中 | | 首轮基础骨架 | `[✓]` 已完成,等待复审 | | Git 提交 | `[ ]` 未开始 | | Git 推送 | `[ ]` 未开始 | 下一步默认从“阶段 1:项目基础工程”和“首轮开发范围”开始执行。 --- ## 二十六、首轮开发执行记录 ### 26.1 已完成,等待复审 - [✓] 建立 `backend` Go 模块和 `scert` CLI 入口。 - [✓] 实现 JSON 配置模型、Windows/Linux 默认目录、配置保存、读取和校验。 - [✓] 实现 `log/slog` 结构化日志输出,日志文件使用受限权限创建。 - [✓] 实现 SQLite 和 MySQL 数据库打开、连接池和 Ping 检查。 - [✓] 实现 SQLite/MySQL 首版迁移脚本,创建设置、域名、任务和审计日志基础表。 - [✓] 实现域名领域模型和 SQL Repository,纳入单域名、泛域名和 SAN 基础校验。 - [✓] 实现应用组装、资源关闭和数据库自动迁移。 - [✓] 实现 `/healthz`、`/api/v1/status`、域名列表、域名创建和域名删除接口。 - [✓] 实现 `version`、`help`、`init`、`status`、`serve`、`domain list` 和 `domain add` 命令。 - [✓] 创建 Vue/Vite 中文前端占位页面和开发代理配置。 - [✓] 补充根 README、后端 README、配置测试、数据库迁移测试和 HTTP API 测试。 ### 26.2 验证结果 - [✓] `go fmt ./...` 通过。 - [✓] `go vet ./...` 通过。 - [✓] `go test ./...` 通过。 - [✓] Windows amd64 可执行文件构建通过。 - [✓] Linux amd64 交叉编译通过。 - [✓] CLI 初始化、状态、域名添加和域名列表流程实测通过。 - [✓] HTTP 服务启动、`/healthz` 和 `/api/v1/status` 接口实测通过。 ### 26.3 后续阶段,不在本轮宣称完成 - [ ] 集成 `go-acme/lego`,完成 Let’s Encrypt Staging/Production 申请。 - [ ] 接入 DNS-01 服务商和 CNAME 委派。 - [ ] 实现自动续期任务调度和证书版本保留。 - [ ] 实现 SSH/SFTP 推送、远程备份和 Nginx/Caddy/Apache reload。 - [ ] 实现部署后的远程 HTTPS 证书链校验。 - [ ] 实现 HTTP API、SMTP 出站通知及重试/HMAC/Bearer Token 配置。 - [ ] 完成管理员认证、完整 Web 管理界面和操作日志页面。 - [ ] 完成 Wails 桌面版、Windows Service 和 Linux systemd。 - [!] 完成 MySQL 5.7/8.0 实例连接和迁移兼容性实测。 ### 26.4 当前状态 | 项目 | 状态 | |---|---| | 首轮基础骨架 | `[✓]` 已完成,等待复审 | | 首轮验证 | `[✓]` 已完成,等待复审 | | 完整证书管理功能 | `[ ]` 未开始 | | Git 提交 | `[ ]` 未开始 | | Git 推送 | `[ ]` 未开始 | --- ## 二十七、首轮开发复审记录 ### 27.1 复审信息 - 复审日期:2026 年 8 月 26 日。 - 复审范围:配置、日志、数据库连接、数据库迁移、域名领域模型、SQL Repository、HTTP API、CLI、Vue/Vite 前端占位页、Windows/Linux amd64 构建和运行流程。 - 复审原则:仅将经过源码核对和实际验证的项目标记为 `[✓]`;缺少真实环境参数的兼容性测试保持 `[!]`。 ### 27.2 复审发现并已修复 - [✓] 修复构建版本常量,统一程序版本为 `0.1.0`,并将配置版本单独作为 `config_version` 返回。 - [✓] 修复 CLI 重复 `help`、默认 `completion` 和主要英文帮助标题,支持 `scert help domain`。 - [✓] 修复 CLI JSON 编码错误被忽略的问题。 - [✓] 修复 SAN 仅检查数量、主域名未稳定纳入完整 SAN 集合以及重复处理的问题。 - [✓] 增加 SAN 逐项域名格式验证和去重测试。 - [✓] HTTP API 不再向客户端返回底层 `err.Error()`,内部错误仅写入服务日志。 - [✓] 状态接口同时返回程序版本和配置版本。 - [✓] 未知数据库驱动不再回退到 SQLite,而是明确拒绝。 - [✓] MySQL DSN 通过驱动解析器规范化,并强制启用 `parseTime` 和 UTC 时间位置。 - [✓] MySQL 迁移不再依赖无法保证回滚的 DDL 事务;所有幂等 DDL 成功后才记录迁移版本。 - [✓] SQLite 迁移继续使用事务,并验证重复迁移不会重复写入版本。 - [✓] Repository 的 `GetByID`、`List`、`Delete` 增加空数据库保护,`IsNotFound` 改为基于 `errors.Is` 判断。 - [✓] 配置版本不兼容时明确拒绝,配置文件覆盖保存和权限收紧通过测试。 - [✓] 已有日志文件会重新收紧权限,结构化 JSON 日志写入通过测试。 - [✓] HTTP 服务增加读取头、读取、写入和空闲超时。 - [✓] 前端补充中文证书类型、域名状态和 HTTPS 模式显示,生产构建通过。 - [✓] 增加 `.gitignore`,忽略后端构建目录、前端依赖目录、前端构建目录和日志文件。 ### 27.3 新增测试覆盖 - [✓] 单域名、泛域名、非法证书类型和泛域名类型匹配测试。 - [✓] SAN 自动包含主域名、去重、最少域名数量和非法 SAN 测试。 - [✓] 非法数据库驱动、MySQL DSN 时间解析和 SQLite 迁移幂等性测试。 - [✓] 四张基础表存在性检查。 - [✓] 配置版本兼容性和覆盖保存测试。 - [✓] Repository 空数据库保护、CRUD 和未找到判断测试。 - [✓] CLI 中文帮助、单一 `help`、禁用 `completion`、子命令帮助和版本字段测试。 - [✓] HTTP 状态版本、SAN 请求、404 和错误信息不泄露测试。 - [✓] JSON 日志内容和非 Windows 权限断言测试。 ### 27.4 本轮验证结果 - [✓] `gofmt` 检查通过。 - [✓] `go vet ./...` 通过。 - [✓] `go test ./...` 通过。 - [✓] `go test -race ./...` 通过。 - [✓] Windows amd64 复审构建通过:`backend/dist/scert-review-windows-amd64.exe`。 - [✓] Linux amd64 复审交叉构建通过:`backend/dist/scert-review-linux-amd64`。 - [✓] `npm.cmd install` 通过,安装 34 个依赖包,审计结果为 0 个已知漏洞。 - [✓] `npm.cmd run build` 通过,Vue/Vite 生产产物已生成到 `frontend/dist`。 - [✓] `scert version` 返回 `0.1.0`。 - [✓] `scert help` 和 `scert help domain` 显示中文帮助,只有一个 `help`,不显示 `completion`。 - [✓] `scert init`、`scert status`、`scert domain add` 和 `scert domain list` 实际流程通过。 - [✓] `scert serve` 实际启动通过,`/healthz`、`/api/v1/status` 返回成功。 - [✓] 严格 UTF-8、无 BOM、无 Unicode 替换字符和无连续乱码问号检查通过。 - [✓] Git 远程名称为 `Scert`,地址为 `https://git.pcux.cn/xuans/Scert.git`。 ### 27.5 阻塞和边界 - [!] MySQL 5.7 实例连接和迁移尚未实测。已确认客户端为 `E:\DB\5.7\bin\mysql.exe`,版本 `5.7.44`,但缺少明确 DSN、端口、账号和密码。 - [!] MySQL 8.0 实例连接和迁移尚未实测。已确认客户端为 `E:\DB\8.0\bin\mysql.exe`,版本 `8.0.45`,但缺少明确 DSN、端口、账号和密码。 - [!] Linux 文件权限当前完成代码实现和交叉构建,仍需在 Ubuntu 22.04 实机验证运行用户、目录属主和 `0600` 权限。 - [!] Windows 安全 ACL 尚未实现;当前 `0600` 调用不能替代完整 Windows ACL 验收。 - [!] 默认直接 HTTPS 和高级内部 HTTPS 仍属于后续阶段,当前 `serve` 仅为 HTTP 基础骨架。 - [!] ACME/lego、DNS Provider、自动续期、远程部署、通知、认证、完整 Web 和 Wails 均未进入本轮完成范围。 ### 27.6 复审结论 | 项目 | 状态 | |---|---| | 首轮基础骨架代码 | `[✓]` 复审通过 | | SQLite 本地流程 | `[✓]` 复审通过 | | CLI 和 HTTP 基础流程 | `[✓]` 复审通过 | | Vue/Vite 前端占位页 | `[✓]` 复审通过 | | Windows/Linux amd64 构建 | `[✓]` 复审通过 | | MySQL 5.7/8.0 实例兼容性 | `[!]` 等待明确连接参数 | | 首轮完整环境验收 | `[!]` 尚未全部完成 | | Git 提交 | `[ ]` 未开始 | | Git 推送 | `[ ]` 未开始 | 当前代码可以继续进入下一阶段开发,但不能宣称 MySQL 5.7/8.0 真实实例兼容性、HTTPS 双模式或完整证书生命周期已经验收通过。 --- ## 二十八、本轮继续开发记录 ### 28.1 实现内容 - [x] CLI 新增 `scert domain edit` 命令,支持修改域名、证书类型、SAN、自动续期、ACME 环境和 DNS 服务商标识。 - [x] CLI 编辑域名时保留原域名 ID 和创建时间,并将证书状态恢复为等待申请,避免配置变化后继续使用旧证书状态。 - [x] CLI 域名帮助内容覆盖新增的编辑命令。 ### 28.2 浏览器复审结果 - [x] 桌面视口验证域名列表、添加域名、编辑域名和删除入口。 - [x] SAN 表单验证主域名、附加域名、测试/生产环境和 DNS 服务商选项。 - [x] 添加重复域名时,页面显示“域名已经存在”,未泄露底层数据库错误。 - [x] 编辑表单正确回显 SAN 域名、ACME 环境、自动续期和 DNS 服务商配置。 - [x] 窄屏视口验证域名卡片布局和页面无横向溢出。 - [x] 低高度视口验证弹窗限制在可视区域内,并可通过弹窗内部滚动查看完整表单。 ### 28.3 本轮质量检查 - [x] `gofmt -l .` 检查通过。 - [x] `go test ./...` 通过。 - [x] `go test -race ./...` 通过。 - [x] `go vet ./...` 通过。 - [x] `npm.cmd run build` 通过。 - [x] CLI 实测完成域名编辑并验证持久化结果。 ### 28.4 当前边界 - [ ] `go-acme/lego` 实际证书申请和 DNS-01 Provider 尚未实现。 - [ ] 自动续期调度、证书版本、远程服务器部署、部署后校验和通知尚未实现。 - [ ] 管理员登录认证、Wails 桌面封装、Windows Service 和 Linux systemd 尚未实现。 - [!] MySQL 5.7/8.0 真实实例兼容性仍需要明确 DSN、端口、账号和密码后验证。 ## 二十九、本轮安装部署开发记录(2026-08-26) ### 29.1 已完成,等待复审 - [x] 当时扩展配置模型:超级管理员、密码重置服务地址和端口、Web 域名/IP、Web 开关、DNS 验证状态、TLS 文件路径;其中独立重置地址和端口方案已由第四十三节的主服务 `/reset` 临时入口方案替代。 - [x] 增加配置兼容归一化,旧配置缺少新增字段时补充安全默认值。 - [x] 当时增加初始化服务 `internal/setup`,校验管理员密码长度、双端口冲突、DNS 验证状态、Web 域名/IP互斥和公网 IP 格式;双端口校验现已取消,只校验 Scert 主服务端口。 - [x] 初始化时只保存管理员 bcrypt 摘要,不保存管理员明文密码。 - [x] 当时 `scert init` 支持交互式填写双端口、第三方邮箱、DNS 凭据引用、证书根目录、Web 域名/IP和 Web 开关;当前初始化流程已取消独立重置端口。 - [x] 当时新增 `scert-admin` 可执行入口和本机回环监听的受保护服务占位接口;回环监听方案现已由第四十三节的无网络监听租约控制器替代。 - [x] 为初始化服务补充未通过 DNS、成功配置、域名/IP冲突测试。 - [x] 新增 Web 初始化状态和提交接口,未初始化时只允许本机访问,并限制请求体最大为 64 KiB。 - [x] Web 初始化接口接入统一初始化服务,保存到实际配置文件路径,并禁止重复初始化。 - [x] 未初始化状态下执行 `scert serve` 时强制仅监听 `127.0.0.1`,初始化完成后需要重启服务应用新端口。 - [x] 当时新增中文 Web 初始化向导,覆盖超级管理员、双端口、第三方邮件服务、DNS 凭据引用、证书目录、Web 域名/公网 IP、HTTPS 模式和 Web 页面开关;当前界面只保留主服务端口并实时预览 `/reset` 地址。 - [x] 初始化向导明确标注真实 DNS 在线测试、`go-acme/lego` 证书申请和 HTTPS 切换尚未接入,避免误报证书签发成功。 - [x] 初始化配置保存成功后自动进入现有域名管理页面。 - [x] Vite 开发服务器支持通过环境变量设置开发端口和后端 API 地址,便于多实例预览和联调。 ### 29.2 尚未完成 - [ ] 集成真实 `go-acme/lego` Web 证书申请、DNS provider 验证和证书部署。 - [ ] 实现 Web 证书本地校验、HTTPS 启动和初始化完成后的 HTTP 关闭。 - [ ] 实现 `/reset` 密码提交、一次性校验码校验与单次消费、bcrypt 密码摘要更新、频率限制和审计日志。 - [ ] 实现 Windows Service、Linux systemd 以及同时安装两个服务的安装器。 - [ ] 实现 Wails 首次启动向导和“是否开启 Web 页面”按钮。 - [ ] 完成公网 IP 证书的 CA、`lego` 和跨平台实测。 - [ ] 实现本机防火墙适配和云安全组提示界面。 ### 29.3 本轮验证 - [✓] `gofmt -w` 通过。 - [✓] `go test ./...` 通过。 - [✓] `go test -race ./...` 通过。 - [✓] `go vet ./...` 通过。 - [✓] `npm.cmd run build` 通过。 - [✓] Web 初始化接口本机状态读取、初始化提交、配置持久化、明文密码不落盘、重复初始化和超大请求测试通过。 - [✓] 浏览器实测初始化状态读取、表单提交、配置保存和初始化后进入域名管理页面通过。 - [✓] 浏览器在 1440×900、1280×720 和移动端 501×845 视口下无横向溢出。 ### 29.4 复审边界 - [✓] Web 初始化接口与初始化向导基础流程复审通过。 - [✓] 初始化阶段本机访问限制、配置持久化和管理员密码摘要存储复审通过。 - [!] DNS 验证勾选项当前只接收外部验证结果,不能替代真实 DNS Provider 在线测试。 - [!] 初始化完成响应不代表证书已经签发,也不代表 HTTPS 已经启用。 - [!] Scert-admin 当前仍是本机 HTTP 服务占位入口,密码重置安全通道尚未完成。 --- ## 三十、DNS 在线验证与加密凭据开发记录(2026-08-26) ### 30.1 已完成,等待复审 - [x] 新增 DNS Provider 目录接口,统一返回 Cloudflare、阿里云 DNS、DNSPod、CNAME 委派、华为云、腾讯云、AWS Route 53、Google Cloud DNS 和其他服务商的字段模型与可用状态。 - [x] 基于 `go-acme/lego` 接入 Cloudflare DNS Provider,在线测试会创建并清理临时 DNS-01 TXT 记录。 - [x] 增加 DNS 凭据字段白名单、必填校验和测试域名格式校验。 - [x] 新增 AES-GCM 敏感信息存储,DNS 明文凭据不写入普通配置文件,主密钥和密文文件使用受限权限。 - [x] 新增 15 分钟有效的 DNS 验证令牌,绑定服务商、测试域名和凭据引用。 - [x] 初始化流程调整为先检查令牌、校验并保存配置,配置保存成功后再消费一次性令牌。 - [x] Web 初始化向导动态读取 Provider 目录并生成普通、密码和 JSON 凭据字段。 - [x] Web 初始化向导增加 DNS 权限测试域名和“测试 DNS API”操作,提交时使用后端签发的凭据引用与验证令牌。 - [x] Provider、凭据或测试域名变化时自动清除旧验证状态,并定时检查验证结果是否过期。 - [x] 所有 Provider 均可在下拉列表中选择并查看字段;未开放适配器明确标识状态并禁止执行在线测试。 - [x] 初始化表单控件补充稳定的 `id` 和 `name`,动态 DNS 字段使用唯一标识。 - [x] 调整辅助文字颜色对比度,提升初始化页面可访问性。 ### 30.2 安全测试与复审结果 - [✓] DNS 验证令牌执行 `Check` 时不消费,执行 `Consume` 后不能再次使用。 - [✓] 管理员、端口等初始化表单校验失败时不消费 DNS 验证令牌。 - [✓] 配置文件保存失败时不消费 DNS 验证令牌。 - [✓] DNS 测试接口拒绝非本机请求,并限制请求体最大为 64 KiB。 - [✓] 未开放 Provider 返回 HTTP 501,不伪报在线验证成功。 - [✓] Provider 错误响应和 DNS 测试响应均不返回用户提交的明文凭据。 - [✓] 501×845 移动视口使用 AWS Route 53 五字段表单复审,无横向溢出。 - [✓] 1440×900 桌面视口使用 Cloudflare 表单复审,无横向溢出。 - [✓] DNS 下拉列表中的九类服务商及其动态字段模型完成浏览器逐项检查。 - [✓] Lighthouse 初始化页面可访问性评分为 100,最佳实践评分为 100。 - [✓] `gofmt -l .`、`go test ./...`、`go test -race ./...`、`go vet ./...`、`npm.cmd run build` 和 `git diff --check` 全部通过。 - [✓] 57 个文本源码和文档文件通过 UTF-8 无 BOM、无 Unicode 替换字符和无连续乱码问号检查。 ### 30.3 当前边界和后续任务 - [ ] 接入阿里云 DNS、DNSPod/腾讯云、华为云、AWS Route 53 和 Google Cloud DNS 在线适配器。 - [ ] 完成 CNAME 委派的目标 Provider 组合验证流程。 - [x] 将 CLI `scert init` 从“凭据引用加手动确认”升级为真实 DNS 在线验证流程;交互输入允许明文查看,验证通过后只保存加密凭据引用。 - [ ] 集成 `go-acme/lego` 真实证书签发、续期和初始化管理后台证书部署。 - [ ] 实现 HTTPS 双模式实际启动和初始化完成后的安全切换。 - [x] 将敏感信息密文文件保存升级为安全原子替换,并补充异常替换失败时保留旧文件的测试。 - [ ] 清理过期、重复测试或放弃初始化所产生的未引用 DNS 凭据。 - [ ] 完成 Scert-admin 受保护的本地密码重置通道、安装器和系统服务。 - [!] MySQL 5.7/8.0 真实实例测试仍等待明确的 DSN、端口、账号和密码;不得通过 PATH 自动判断 MySQL 实例。 ## 五十七、配置凭据明文查看与加密存储复审记录(2026-08-28) ### 57.1 需求清单 - [x] 配置阶段允许用户在 CLI 中明文查看 DNS API 凭据,便于核对输入内容。 - [x] 配置阶段允许用户在 Web 初始化页面中切换 DNS 凭据的明文显示和隐藏显示。 - [x] DNS 凭据在线验证时只在进程内存中传递给 Provider 测试器。 - [x] 验证成功后使用 AES-GCM 加密写入敏感信息存储,普通配置文件只保存 `secret://` 凭据引用。 - [x] 证书申请和续期通过凭据引用从敏感信息存储解密后创建 DNS Provider,不要求业务配置保存明文凭据。 - [x] 验证失败、初始化提交失败或配置保存失败时,不消费验证令牌,不把明文凭据写入普通配置或日志。 ### 57.2 实现和测试状态 - [x] CLI 动态读取 DNS Provider 凭据字段,并在明文输入提示中明确说明提交后的加密保存边界。 - [x] Web 初始化向导新增“显示凭据明文”控制项;隐藏状态使用掩码显示,JSON 凭据不在隐藏状态下暴露内容。 - [x] 增加 CLI 凭据输入、验证、加密保存、输入清空和临时凭据清理测试。 - [x] 增加最终 `scert.json` 只保存 DNS 凭据引用、不保存 Token 或字段名的测试。 - [x] 增加证书服务根据加密凭据引用解密后创建 DNS Provider 的测试。 - [x] 增加敏感信息密文文件不包含明文凭据、权限受限和原子替换失败保留旧文件的测试。 ### 57.3 验证结果 - [✓] `go test -race ./...` 通过。 - [✓] `go vet ./...` 通过。 - [✓] 前端 `npm.cmd run build` 通过。 - [✓] 代码和文档中未新增明文测试凭据输出;测试使用的凭据仅用于断言,未写入仓库文件。 ### 57.4 复审边界 - [!] 浏览器真实操作时,初始化页面仍应限制为本机访问;明文凭据只应在用户明确操作期间短时显示。 - [!] 生产环境仍需继续执行真实 DNS Provider、Let’s Encrypt、MySQL 5.7/8.0 和远程部署验收;本轮自动化测试不替代实机验收。 - [!] 未引用敏感信息的定期清理策略仍需后续实现,不能在本轮擅自删除可能仍被业务引用的密文记录。 ### 57.5 复审结论 本轮“配置时可明文查看、保存时加密、调用时按引用解密”的代码链路和自动化测试已完成并通过复审。明文凭据不进入普通配置文件、业务数据库字段、日志、错误响应或 Git 文件;生产级部署和真实外部服务验收仍按既有边界执行。 --- ## 三十一、敏感信息文件原子写入复审记录(2026-08-26) ### 31.1 已完成,等待复审 - [x] `secrets.json` 改为在目标目录创建唯一临时文件,不再直接覆盖正式密文文件。 - [x] 临时文件在替换前完成 `0600` 权限设置、内容写入、文件同步和关闭。 - [x] 使用同目录重命名替换正式文件,Linux 下额外同步所在目录。 - [x] 原子替换失败时保留原密文文件,并自动清理未提交的临时文件。 - [x] 原子写入完成后继续收紧正式密文文件权限。 ### 31.2 测试与复审结果 - [✓] Windows amd64 上首次写入和覆盖已有 `secrets.json` 测试通过。 - [✓] 模拟替换失败时,旧密文文件内容保持不变。 - [✓] 成功与失败路径均不残留 `.secrets.json.tmp-*` 临时文件。 - [✓] 非 Windows 平台的 `0600` 权限断言已经加入测试。 - [✓] `go test ./internal/secretstore -count=1 -v` 通过。 - [✓] `gofmt -l .`、`go test ./...`、`go test -race ./...` 和 `go vet ./...` 通过。 - [✓] Linux amd64、`CGO_ENABLED=0` 全量 Go 构建通过。 - [✓] `npm.cmd run build` 通过。 ### 31.3 后续边界 - [ ] 为敏感信息存储增加删除接口,并清理过期、重复测试或放弃初始化产生的未引用凭据。 - [ ] 在 Ubuntu 22.04 实机复审目录同步和 `0600` 权限。 - [ ] Windows 安装阶段需要使用 ACL 将主密钥和密文文件限制为 Scert 服务账号、管理员和 SYSTEM 可访问。 --- ## 三十二、初始化本机防火墙自动放行开发记录(2026-08-26) ### 32.1 需求清单 - [x] 初始化时自动检查并放行 Scert 主服务 TCP 端口。 - [x] `Scert-admin` 继续只监听本机,不创建公网或局域网入站规则。 - [x] Windows 10/11 支持 Windows Defender 防火墙规则。 - [x] Ubuntu 支持已启用的 UFW,CentOS/Rocky Linux 支持已启用的 firewalld。 - [x] 防火墙未启用时不主动启用,并返回明确的“无需创建规则”状态。 - [x] 权限不足或规则创建失败时阻止初始化静默成功。 - [x] 云安全组不自动修改,初始化完成后继续提示用户手动放行主服务端口。 ### 32.2 开发任务状态 - [x] 新增 `internal/firewall` 适配层和可注入命令执行器。 - [x] 所有端口先校验为 `1-65535`,系统命令通过参数数组执行,不拼接用户输入。 - [x] Windows 规则使用固定名称 `Scert Web TCP {端口}`,支持状态检查、存在检查、创建和回滚。 - [x] UFW 支持启用状态检查、已有规则识别、创建和本次规则回滚。 - [x] firewalld 支持运行状态检查、永久规则查询、创建、重新加载和失败清理。 - [x] Web 初始化接入本机防火墙事务,并在响应中返回后端、规则名称、端口、是否新建和中文状态。 - [x] CLI 初始化复用同一防火墙管理接口,并输出本机防火墙结果和云安全组提示。 - [x] 配置保存失败时只回滚本次初始化新创建的规则,保留原本已存在的规则。 - [x] 初始化界面明确显示“本机防火墙自动配置、云安全组仍需手动放行”。 ### 32.3 自动化测试状态 - [x] 无效端口在执行系统命令前被拒绝。 - [x] Windows 防火墙未启用时不创建规则。 - [x] Windows、UFW 和 firewalld 创建命令均验证为独立参数调用。 - [x] 已存在的 UFW 规则不会重复创建。 - [x] firewalld 重新加载失败时清理本次新增的永久规则。 - [x] firewalld 权限错误不会被误报为“防火墙未启用”。 - [x] Web 初始化只开放主服务端口,不开放密码重置端口。 - [x] Web/CLI 配置保存失败时回滚本次新建规则。 - [x] 配置保存失败时保留初始化前已存在的防火墙规则。 - [x] 防火墙创建失败时不保存初始化配置,也不消费 DNS 验证令牌。 ### 32.4 等待复审 - [x] 代码格式化、单元测试、竞态检查、静态检查和跨平台构建等待本轮统一执行。 - [!] Windows 10/11、Ubuntu 22.04/24.04 和 CentOS/Rocky Linux 实机规则创建需要在安装器提供提权运行方式后复审。 - [!] 云安全组属于云厂商外部资源,本阶段不自动修改。 ## 三十三、Scert Logo 与浏览器图标接入开发记录(2026-08-26) ### 33.1 需求清单 - [x] 使用 `frontend/logo/Scert.png` 作为 Web 管理界面 Logo。 - [x] 使用 `frontend/logo/Scert.png` 作为浏览器标签页图标。 - [x] Logo 使用透明背景,避免在不同页面背景上出现白色方块。 - [x] 初始化检查页、管理首页和首次配置页统一使用同一品牌资源。 ### 33.2 开发任务状态 - [x] 将原有字母占位 Logo 替换为 `Scert.png` 图片组件。 - [x] 将 `index.html` 中的内嵌 SVG favicon 替换为 PNG favicon。 - [x] 配置 Vite `publicDir`,使 favicon 通过 `/Scert.png` 提供。 - [x] 为透明 Logo 增加 `object-fit: contain` 和阴影样式,保留原图比例。 - [x] 增加移动端 Logo 尺寸适配,避免初始化页布局溢出。 ### 33.3 验证状态 - [x] `npm.cmd run build` 前端生产构建通过。 - [x] `git diff --check` 未发现空白错误。 - [x] 浏览器实测 favicon 地址为 `/Scert.png`,图片加载尺寸为 `1254×1254`。 - [x] 浏览器 Canvas 检测图片四角 Alpha 为 `0`、中心 Alpha 为 `255`,确认透明背景有效。 ### 33.4 等待复审 - [x] Logo 与浏览器图标接入完成,等待用户复审视觉效果。 ## 三十四、Scert-admin systemd 手动启停边界开发记录(2026-08-26) ### 34.1 需求清单 - [x] `Scert-admin` 不允许开机自启动。 - [x] 日常支持的启停命令仅为 `systemctl start Scert-admin` 和 `systemctl stop Scert-admin`。 - [x] `Scert-admin` 不配置自动重启,不提供 `ExecReload`,不创建公网防火墙规则。 - [x] `Scert-admin` 继续使用 `Scert` 用户运行;本节最初采用回环监听,现已由第四十三节改为不监听任何 TCP/UDP 端口。 - [x] 安装或升级阶段允许使用一次 `systemctl daemon-reload` 加载新 unit,但不得因此启动或启用 `Scert-admin`。 ### 34.2 开发任务状态 - [x] 新增 `deploy/systemd/Scert-admin.service`,不包含 `[Install]` 和 `WantedBy=`,因此不会通过 `systemctl enable` 注册开机启动。 - [x] 新增 `deploy/systemd/Scert.service`,保留核心服务独立的 systemd 服务定义。 - [x] 新增 `deploy/systemd/Scert-admin服务管理说明.md`,明确安装阶段和日常运维阶段的命令边界。 - [x] 增加自动化检查,验证 `Scert-admin.service` 使用 `Scert` 用户、`Restart=no`,且没有自动启动目标、自动重启和 reload 配置。 - [x] 原非回环监听拒绝测试已被无网络监听验证替代;当前自动化检查要求 systemd 只允许 `AF_UNIX`,并禁止 `AF_INET` 和 `AF_INET6`。 ### 34.3 安全边界与未完成项 - [x] 未使用 `systemctl mask`、`RefuseManualStart` 或 `RefuseManualStop`,避免阻断用户明确要求的 `start` 和 `stop`。 - [x] 已明确 systemd 无法阻止 root 或等效权限操作者调用 `status`、`restart`、`kill` 等底层管理命令;本轮实现的是“不支持、不自动执行、不对外暴露”,不是虚假的绝对权限隔离。 - [x] Linux 安装器基础流程已完成,覆盖 unit 文件复制、`Scert` 用户创建、目录授权、自定义证书根目录和一次性 `daemon-reload`,等待 Linux 实机复审。 - [!] Ubuntu 22.04、Ubuntu 24.04、CentOS/Rocky Linux 和 Debian 实机安装与启停复审待完成。 ## 三十五、Linux 安装器基础流程开发记录(2026-08-26) ### 35.1 需求清单 - [x] 安装包同时安装 `scert` 和 `scert-admin` 两个 Linux amd64 可执行文件。 - [x] 创建专用 `Scert` 系统用户和用户组,并禁止交互式登录。 - [x] 创建 `/scert`、配置、数据、日志、备份、文档和证书目录,不删除已有用户数据。 - [x] 默认使用 `/ssl`,同时允许通过安装参数指定其他安全绝对路径作为证书根目录。 - [x] 安装 `Scert.service` 和 `Scert-admin.service`,只执行一次 `systemctl daemon-reload`。 - [x] 安装器不得启动、重启或启用 `Scert-admin`,不得为其创建公网防火墙规则。 - [x] 修正技术架构和图形初始化流程中“自动启动 Scert-admin”的旧描述。 ### 35.2 开发任务状态 - [x] 新增 `deploy/install-linux.sh`,支持环境、root 权限、依赖命令和安装产物检查。 - [x] 安装器以幂等方式创建服务用户、默认目录、二进制文件、文档和 systemd unit。 - [x] 对现有 `scert.json`、`master.key` 和 `secrets.json` 收紧为 `Scert` 用户所有及 `0600` 权限。 - [x] 为自定义证书根目录生成 `Scert.service.d/10-certificate-path.conf`,避免 systemd 文件系统保护阻断证书写入。 - [x] 修正两个 systemd unit 的 `Documentation` 为安装后的本地文档路径。 - [x] 新增 `deploy/README.md` 和 `Scert服务管理说明.md`。 - [x] 新增安装器静态策略测试,检查目录、用户、自定义证书路径、单次 daemon-reload、禁止启动 Scert-admin 和禁止直接操作防火墙。 ### 35.3 验证状态 - [x] `go test ./internal/admin` 通过。 - [x] `gofmt -l .`、`go test ./...`、`go test -race ./...` 和 `go vet ./...` 通过。 - [x] Windows amd64 的 `scert`、`scert-admin` 构建通过。 - [x] Linux amd64、`CGO_ENABLED=0` 的 `scert`、`scert-admin` 交叉构建通过。 - [x] `npm.cmd run build` 前端生产构建通过。 - [x] `git diff --check` 通过,新增部署文件严格 UTF-8、无 BOM、无替换字符;Shell 和 systemd 文件使用 LF 换行。 - [x] 使用 `mvdan.cc/sh/v3/cmd/shfmt@v3.10.0` 对 `install-linux.sh` 执行只读 AST 解析,Bash 语法通过。 - [!] 当前 Windows 开发机未安装 WSL 或 Bash,安装器的 Linux 命令行为仍需在目标系统实机执行。 - [!] Ubuntu 22.04/24.04、Debian、CentOS/Rocky Linux 的 root 安装、目录属主和 systemd 行为仍需实机复审。 ### 35.4 安全边界 - [x] 安装器不会自动启动任何服务;核心服务需在初始化、证书部署和校验完成后按运维流程启动。 - [x] `Scert-admin` 默认保持停止状态,安装结果只提示 `systemctl start Scert-admin` 和 `systemctl stop Scert-admin`。 - [x] systemd 无法阻止 root 调用底层管理命令,本阶段保证的是不自动执行、不注册开机启动、不自动重启和不对外暴露。 - [x] 自定义证书目录限制为规范化安全绝对路径,拒绝受保护系统目录、`/scert` 下路径、符号链接和不安全路径片段;`/var` 下仅允许 `/var/lib/scert` 专用路径。 --- ## 三十六、Linux 安装器复审记录(2026-08-26) ### 36.1 复审范围 - [x] 复审 `deploy/install-linux.sh` 的路径校验、符号链接防护、用户创建、目录权限、幂等性和 systemd 操作边界。 - [x] 复审 `Scert.service` 与 `Scert-admin.service` 的运行用户、文件系统保护、自动重启、开机启动和监听范围。 - [x] 复审安装器与 CLI 初始化默认路径的联动,以及已有配置、数据库、日志和备份目录的权限恢复。 - [x] 复审自动化测试、Shell AST 解析、后端测试、竞态测试、静态检查和前端生产构建。 - [x] 复审需求确认文档、技术架构文档、部署说明与当前实现的明显矛盾。 ### 36.2 本轮修复 - [x] 拒绝 `/etc`、`/usr`、`/var` 等受保护系统路径作为证书根目录;`/var` 仅开放 `/var/lib/scert` 专用路径。 - [x] 拒绝证书目录和 `/scert`、systemd 文件、已安装二进制及文档路径中的符号链接,避免 root 安装器跟随链接修改非预期位置。 - [x] 保持用户确认的 `Scert` 大写运行用户名称;普通创建失败且系统支持 `--badname` 时兼容重试,不支持时明确失败,不降级为其他用户名。 - [x] 对 `/scert/conf`、`/scert/data`、`/scert/log` 和 `/scert/backups` 中已有 Scert 管理数据恢复属主,避免历史 root 初始化文件阻断服务运行。 - [x] 安装器写入 `/scert/conf/installation.json`,记录规范化证书根目录;Linux CLI 初始化默认值会读取该记录,解决 `--certificate-dir` 与初始化配置脱节问题。 - [x] `Scert-admin` 配置和服务层仅接受字面量 `127.0.0.1` 或 `::1`,不再依赖 `localhost` 名称解析。 - [x] 保持 `Scert-admin` 不含 `[Install]`、不自动重启、不提供 `ExecReload`,安装器不执行其 `start`、`restart` 或 `enable` 操作。 ### 36.3 自动化验证结果 - [✓] `go test ./...` 通过。 - [✓] `go test -race ./...` 通过。 - [✓] `go vet ./...` 通过。 - [✓] `npm.cmd run build` 前端生产构建通过。 - [✓] 使用 `mvdan.cc/sh/v3/cmd/shfmt@v3.10.0` 对 `deploy/install-linux.sh` 执行只读 Shell AST 解析通过。 - [✓] Windows amd64 和 Linux amd64(`CGO_ENABLED=0`)的 `scert`、`scert-admin` 构建通过。 - [✓] `git diff --check` 通过。 ### 36.4 尚未通过的实机验收 - [!] 当前 Windows 开发机未安装 WSL 或 Bash,无法执行真实 Linux 安装器命令链。 - [!] Ubuntu 22.04、Ubuntu 24.04、Debian、CentOS/Rocky Linux 的 root 安装、`Scert` 大写用户创建、目录属主和权限仍需实机验证。 - [!] 不同发行版的 `groupadd/useradd --badname` 支持情况仍需实机验证。 - [!] systemd unit 注册、`daemon-reload`、核心服务启停、`Scert-admin` 手动启停、无网络监听限制和 `/reset` 租约激活仍需实机验证。 - [!] 本机防火墙初始化、云安全组放行、ACME DNS 在线验证、Let’s Encrypt 证书申请、HTTPS 切换和部署后校验不属于本轮安装器复审证据,不能标记为完成。 ### 36.5 复审结论 当前结论为:**Linux 安装器代码与自动化验证通过,Linux 实机安装部署尚未验收通过;Scert 完整产品仍处于部分完成状态。** 本轮没有提交 Git、推送远程仓库或删除文件。后续只有在目标 Linux 环境完成安装器、systemd、权限、服务生命周期和防火墙实测后,才可以将平台安装阶段的实机项目标记为 `[✓]`。 ## 三十七、证书申请与自动续期核心开发记录(2026-08-26) ### 37.1 本轮需求清单 - [x] 使用 `go-acme/lego` 调用 Let’s Encrypt DNS-01 申请证书。 - [x] 支持单域名、泛域名和 SAN 域名列表统一提交申请。 - [x] ACME 账户私钥和注册状态通过加密敏感信息存储持久化,并按 staging/production 隔离。 - [x] 申请成功后校验证书、私钥匹配关系、证书有效期和全部申请域名覆盖关系。 - [x] 证书文件通过原子写入保存,替换前自动备份,申请失败不覆盖旧证书。 - [x] 增加 `scert domain issue --id <域名ID>` 手动申请或续期命令。 - [x] 主服务启动时执行一次自动续期检查,之后按 24 小时周期检查。 ### 37.2 开发任务状态 - [x] 增加 ACME 账户存储层,支持生成、读取和保存账户私钥及注册状态。 - [x] 增加证书申请服务,串联域名配置、DNS 凭据、Provider、Lego Issuer 和证书文件存储。 - [x] 增加证书状态更新接口,记录 `issuing`、`valid` 和 `failed` 状态。 - [x] 增加自动续期调度器,支持阈值筛选、初次证书申请和并发执行保护。 - [x] 增加 SAN、泛域名、申请失败保留旧证书和账户持久化测试。 ### 37.3 本轮验证结果 - [✓] `gofmt -w` 通过。 - [✓] `go test ./...` 通过。 - [✓] `go test -race ./...` 通过。 - [✓] `go vet ./...` 通过。 - [✓] Windows amd64 的 `scert` 和 `scert-admin` 构建通过。 - [✓] Linux amd64、`CGO_ENABLED=0` 的 `scert` 和 `scert-admin` 构建通过。 - [✓] 前端 `npm.cmd run build` 通过。 - [✓] `git diff --check` 通过。 ### 37.4 当前边界 - [!] 本轮未使用真实 DNS 凭据申请 Let’s Encrypt 证书,在线 DNS Provider 和 CA 流程仍需目标环境实机验证。 - [!] 当前只接入已有可用的 DNS Provider 工厂;其他 Provider、CNAME 委派、服务器 SSH 部署和部署后 HTTPS 校验尚未完成。 - [!] `scert domain issue` 已具备核心调用入口,但管理员认证、操作审计和 Web 端手动申请入口尚未接入。 ## 三十八、自有证书导入核心开发记录(2026-08-27) ### 38.1 本轮需求清单 - [x] 允许用户通过 CLI 指定证书、私钥和可选签发者证书文件。 - [x] 导入前验证证书和私钥匹配、有效期正常,并覆盖托管域名、泛域名或全部 SAN。 - [x] 导入成功后使用统一证书目录、备份和原子写入策略保存文件。 - [x] 导入失败时不写入或覆盖托管证书。 ### 38.2 开发任务状态 - [x] 增加证书导入服务 `certificate.Service.Import`。 - [x] 增加 `scert domain import --id <域名ID> --certificate <证书> --private-key <私钥> [--issuer <签发者证书>]` 命令。 - [x] 增加 SAN 导入成功和域名不匹配拒绝导入测试。 - [x] 增加证书尚未生效和证书过期校验逻辑。 ### 38.3 当前验证状态 - [✓] `gofmt -w` 通过。 - [✓] `go test ./...` 通过。 - [✓] `go test -race ./...` 通过。 - [✓] `go vet ./...` 通过。 - [✓] Windows amd64 和 Linux amd64、`CGO_ENABLED=0` 的双服务构建通过。 - [✓] 前端 `npm.cmd run build` 通过。 - [✓] `git diff --check` 通过。 ### 38.4 当前边界 - [!] 本轮仅提供 CLI 导入入口,Web 上传接口和管理页面尚未接入。 - [!] 导入完成后自动推送远程服务器、重载 Nginx/Caddy/Apache 和 HTTPS 在线校验尚未实现。 ## 三十九、多服务器部署核心开发记录(2026-08-27) ### 39.1 本轮需求清单 - [x] 定义服务器连接配置:地址、SSH 端口、用户、私钥引用和主机指纹。 - [x] 定义远程证书、完整证书链和私钥路径。 - [x] 支持 Nginx、Caddy、Apache 默认 reload 命令及自定义命令。 - [x] 支持证书文件远程临时上传、原子替换和私钥权限 `0600`。 - [x] 支持部署前备份、reload 失败回滚和无旧文件场景清理。 - [x] 汇总全部成功、部分成功和全部失败结果。 ### 39.2 开发任务状态 - [x] 增加 `internal/deployment` 部署模型、客户端接口和部署事务服务。 - [x] 增加真实 SSH/SFTP 客户端适配层,仅允许 SSH 私钥认证。 - [x] 增加 SSH 连接超时和固定主机指纹校验。 - [x] 增加远程命令参数校验和 shell 参数安全转义。 - [x] 增加内存远程客户端测试,覆盖成功部署、备份保留、reload 失败回滚和部分成功。 ### 39.3 当前验证状态 - [✓] 部署核心和 SSH/SFTP 适配层定向测试通过。 - [✓] 服务器删除使用事务清理域名关联,避免产生悬空关联,并通过仓储测试。 - [✓] `gofmt`、`go test ./...`、`go test -race ./...` 和 `go vet ./...` 通过。 - [✓] 前端 `npm.cmd run build` 通过。 - [✓] Windows amd64 和 Linux amd64(`CGO_ENABLED=0`)的 `scert`、`scert-admin` 构建通过。 - [✓] `git diff --check` 通过。 ### 39.4 本轮新增联动任务 - [✓] 将服务器仓储和部署服务接入 `app.App`。 - [✓] 将证书申请、续期、导入统一接入“保存证书后部署到关联服务器”工作流。 - [✓] 增加 Web `POST /api/v1/domains/:id/issue` 手动申请/续期接口。 - [✓] 部署部分失败时保留部署报告,并将域名证书状态标记为 `error`。 - [✓] 为证书工作流增加关联服务器部署成功和失败状态测试。 ### 39.5 当前边界 - [!] 服务器配置的 Web/CLI 增删改查入口尚未实现,本轮仅完成数据库仓储和核心联动。 - [!] 尚未在 Windows 10/11、Ubuntu 22.04/24.04、Debian、CentOS/Rocky Linux 和真实 Nginx/Caddy/Apache 环境连接验证。 - [!] 远程备份清理策略、部署后 HTTPS 在线校验、邮件通知和操作审计仍待后续任务实现。 ## 四十、服务器管理入口与前端配置视图开发记录(2026-08-27) ### 40.1 本轮需求清单 - [x] 提供服务器 Web 管理接口:列表、详情、添加、修改和删除。 - [x] 提供域名服务器关联 Web 接口:查询关联和整体替换关联。 - [x] 提供服务器 CLI 管理命令及域名关联命令。 - [x] 前端增加部署服务器列表、添加、编辑和删除配置界面。 - [x] 前端域名表单增加关联部署服务器多选配置。 ### 40.2 开发任务状态 - [x] 将服务器仓储接入 Web API,并统一校验服务器配置和默认 reload 命令。 - [x] 将服务器仓储接入 CLI:`server list/show/add/edit/delete`。 - [x] 增加域名关联 CLI:`domain servers list/set`。 - [x] 删除服务器和域名时事务清理 `domain_servers` 关联。 - [x] 增加 Web/仓储集成测试和 CLI 帮助回归测试。 - [x] 前端完成服务器管理和域名关联交互。 ### 40.3 本轮验证状态 - [✓] `gofmt`、`go test ./...`、`go test -race ./...` 和 `go vet ./...` 通过。 - [✓] 前端 `npm.cmd run build` 通过。 - [✓] 服务器 API 集成测试通过,覆盖创建、关联、删除和关联清理。 - [✓] `git diff --check` 通过。 ### 40.4 当前边界 - [!] 服务器 SSH 私钥内容仍需通过敏感信息存储单独录入,当前管理表单只配置 `private_key_ref`,不会上传明文私钥。 - [!] Web 管理后台认证、邮件通知、证书上传、部署后 HTTPS 校验和操作审计仍待后续接入。 - [!] 真实远程 Windows 10/11、Ubuntu、Debian、CentOS/Rocky Linux 及 Nginx/Caddy/Apache 环境仍需实机验收。 ## 四十一、SSH 部署私钥安全管理开发记录(2026-08-27) ### 41.1 本轮需求清单 - [✓] SSH 部署私钥和可选口令必须进入本机加密敏感信息存储,不写入业务数据库。 - [✓] Web API、CLI 和前端只能返回私钥名称、安全引用、算法、公钥指纹和更新时间。 - [✓] 服务器新增和修改时只能选择真实存在的 SSH 私钥引用。 - [✓] 正在被部署服务器使用的 SSH 私钥禁止删除。 - [✓] SSH 部署客户端支持无口令私钥和带口令私钥。 - [✓] 提供 Web 和 CLI 的 SSH 私钥录入、列表及删除入口。 ### 41.2 开发任务状态 - [✓] 扩展 `secretstore.Store`,增加按引用前缀列出元数据和删除敏感信息能力。 - [✓] 增加 `internal/sshkey` 服务,校验 RSA、ECDSA、Ed25519 和 OpenSSH 私钥并生成 SHA256 公钥指纹。 - [✓] 增加 `GET /api/v1/ssh-keys`、`POST /api/v1/ssh-keys` 和 `DELETE /api/v1/ssh-keys/:id`。 - [✓] 增加 `scert ssh-key list/add/delete`,私钥和口令均从文件读取,不作为命令行参数传入。 - [✓] 服务器 Web API 和 CLI 保存配置前校验 `private_key_ref`,删除私钥前检查服务器占用状态。 - [✓] 前端增加 SSH 私钥管理面板、加密录入弹窗和服务器私钥下拉选择,并在保存或取消后清空私钥表单内存。 ### 41.3 本轮验证状态 - [✓] `go test ./...` 通过。 - [✓] `go test -race ./...` 通过。 - [✓] `go vet ./...` 通过。 - [✓] Windows amd64 和 Linux amd64、`CGO_ENABLED=0` 的 `scert`、`scert-admin` 构建通过。 - [✓] 前端 `npm.cmd run build` 通过。 - [✓] 浏览器模拟 API 联动检查通过:私钥保存后不显示明文或口令,再次打开录入弹窗字段为空。 - [✓] 浏览器模拟 API 联动检查通过:服务器可以选择私钥引用,使用中的私钥删除时显示 HTTP 409 中文错误。 - [✓] 移动端宽度检查未发现横向溢出,顶部操作按钮按两列换行。 - [✓] 带口令私钥创建、错误口令拒绝和部署客户端带口令私钥解析回归测试通过。 - [✓] SSH 私钥 1 MiB、口令 4096 字节及 HTTP 请求体 2 MiB 限制回归测试通过。 - [✓] `go mod verify` 和 `git diff --check` 通过。 ### 41.4 当前边界 - [!] 浏览器检查使用模拟 API,没有向浏览器或仓库写入真实 SSH 私钥。 - [!] 尚未连接真实 SSH/SFTP 服务器验证无口令和加密私钥登录。 - [!] Windows 10/11、Ubuntu 22.04/24.04、Debian、CentOS/Rocky Linux 以及真实 Nginx/Caddy/Apache 环境仍需实机验收。 - [!] 管理后台登录认证与 API 访问保护尚未接入;在认证完成前,不应将当前管理接口直接暴露到公网。 - [!] CLI 与 Web 多进程并发修改 SSH 私钥和服务器引用时,检查与写入之间尚无跨进程原子性保证;后续需通过数据库外键、命名锁或统一事务协调服务增强。 ## 四十二、远程证书目录模板优化开发记录(2026-08-27) ### 42.1 本轮需求清单 - [✓] 远程服务器证书目录统一采用 `/ssl/{域名}/{证书类型}/`。 - [✓] 单域名证书目录使用 `single`,泛域名证书目录使用 `wildcard`,SAN 多域名证书目录使用 `san`。 - [✓] 证书、完整证书链和私钥默认路径分别为 `cert.pem`、`fullchain.pem` 和 `key.pem`。 - [✓] 泛域名的目录名称去除 `*.`,例如 `*.example.com` 使用 `/ssl/example.com/wildcard/`。 - [✓] 同一服务器关联多个域名时,部署流程按当前域名生成实际路径,避免证书互相覆盖。 - [✓] 自定义远程路径继续保留,并支持 `{域名}`、`{证书类型}`、`{domain}` 和 `{certificate_type}` 占位符。 ### 42.2 开发任务状态 - [✓] 在部署模型中增加统一的远程证书默认路径模板。 - [✓] 服务器路径为空时,由后端规范化逻辑自动补充默认模板。 - [✓] 证书部署工作流读取域名名称和证书类型,并在连接远程服务器前解析路径模板。 - [✓] Web 服务器配置表单直接显示真实默认模板,并说明占位符替换规则。 - [✓] API 允许省略三个远程证书路径字段,统一采用后端默认模板。 - [✓] CLI 为三个远程证书路径参数设置默认模板,不再强制用户填写。 - [✓] 未识别的路径占位符返回中文错误,不允许原样部署到远程服务器。 ### 42.3 目录示例 ```text /ssl/ ├── ssh/ └── example.com/ ├── single/ │ ├── cert.pem │ ├── fullchain.pem │ └── key.pem ├── wildcard/ │ ├── cert.pem │ ├── fullchain.pem │ └── key.pem └── san/ ├── cert.pem ├── fullchain.pem └── key.pem ``` ### 42.4 本轮验证状态 - [✓] 单域名、泛域名和 SAN 路径解析测试通过。 - [✓] 同一服务器关联多个域名的目录隔离测试通过。 - [✓] 自定义路径保留、英文占位符兼容和未知占位符拒绝测试通过。 - [✓] API 省略路径字段后采用默认模板的集成测试通过。 - [✓] CLI 默认路径参数和非必填状态测试通过。 - [✓] `go test ./...` 通过。 - [✓] `go test -race ./...` 通过。 - [✓] `go vet ./...` 通过。 - [✓] 前端 `npm.cmd run build` 通过。 - [✓] Windows amd64 和 Linux amd64、`CGO_ENABLED=0` 的 `scert`、`scert-admin` 构建通过。 - [✓] `git diff --check` 通过。 ### 42.5 当前边界 - [!] 本轮调整的是远程服务器证书部署路径,不修改本机证书版本化保存结构。 - [!] `/ssl/ssh` 仅作为 SSH 相关目录规划或用户文件来源目录;Scert 管理的 SSH 私钥和口令仍保存在本机加密敏感信息存储中,不写入普通明文目录。 - [!] Windows 远程服务器的实际证书路径仍需根据目标 SSH/SFTP 服务和 Web 服务配置由用户自定义,并在真实环境中验收。 ## 四十三、Scert-admin 无独立端口与 `/reset` 临时入口开发记录(2026-08-27) ### 43.1 本轮需求清单 - [✓] 密码重置服务取消独立监听端口,初始化流程只配置 Scert 主服务端口。 - [✓] 根据 Web 管理域名或公网 IP 自动生成 `/reset` 地址。 - [✓] `/reset` 公开地址始终使用 `https://域名或IP/reset`,不暴露主服务监听端口,也不增加新的防火墙或云安全组端口。 - [✓] `Scert-admin` 默认不启动,不允许开机自启动,日常控制仍只支持 `systemctl start Scert-admin` 和 `systemctl stop Scert-admin`。 - [✓] `/reset` 只在 `Scert-admin` 显式启动并持有有效租约时临时开放,其他时间隐藏为 `404`。 ### 43.2 开发任务状态 - [✓] 删除配置模型、初始化 API、CLI 和 Web 初始化向导中的独立重置主机与端口字段。 - [✓] 配置模型新增 `ResetURL()`,支持域名、IPv4 和 IPv6,并统一生成不带主服务端口的 `https://域名或IP/reset`。 - [✓] 将 `scert-admin` 从独立 HTTP 服务改为无网络监听的短时租约控制器。 - [✓] 启动时生成一次性校验码,状态文件只保存 SHA-256 摘要,不保存明文校验码。 - [✓] 租约有效期设置为 90 秒,每 30 秒刷新;正常停止立即失效,异常退出后自动过期。 - [✓] Scert 主服务注册固定 `/reset` 路由,未激活、状态读取失败、停止或租约过期时返回 `404`。 - [✓] 激活页面增加禁止缓存、禁止索引、禁止引用来源、内容安全策略和禁止被嵌入的响应限制。 - [✓] systemd 单元设置 `Restart=no`、`RuntimeMaxSec=30min` 和 `RestrictAddressFamilies=AF_UNIX`,阻止 `Scert-admin` 建立 IPv4/IPv6 网络监听。 - [✓] 前端初始化界面删除独立重置端口,增加根据域名/IP与主端口实时生成的 `/reset` 地址预览。 - [✓] 同步需求确认文档、Linux 部署说明和两个 systemd 服务管理说明;历史双端口与回环监听记录保留并标注已被本节替代。 ### 43.3 自动化复审结果 - [✓] `gofmt -l .` 无待格式化文件。 - [✓] `go test ./...` 通过。 - [✓] `go test -race ./...` 通过。 - [✓] `go vet ./...` 通过。 - [✓] `go mod verify` 通过。 - [✓] 前端 `npm.cmd run build` 通过。 - [✓] Windows amd64、`CGO_ENABLED=0` 的 `scert` 和 `scert-admin` 构建通过。 - [✓] Linux amd64、`CGO_ENABLED=0` 的 `scert` 和 `scert-admin` 构建通过。 - [✓] 相关源文件保持 UTF-8 无 BOM。 - [✓] `git diff --check` 通过。 ### 43.4 当前安全边界与未完成项 - [!] 当前 `/reset` 仅为中文占位页面,尚未实现密码提交接口,不能视为已经具备完整密码重置能力。 - [!] 后续必须实现一次性校验码验证与单次消费、新密码复杂度校验、bcrypt 摘要更新、请求频率限制、CSRF/重放防护和审计日志。 - [!] 当前基础实现会把一次性校验码写入标准输出;systemd 会接管服务标准输出。正式上线密码重置前必须实现不把明文校验码长期保留在持久日志中的受保护本地呈现机制。 - [!] Scert 核心服务的真实 HTTPS 终止、证书加载和高级反向代理模式尚未完成;在这些能力完成前,自动生成的 `https://.../reset` 地址属于目标配置地址,不代表当前开发服务已经完成生产级 HTTPS 暴露。 - [!] Windows 10/11 与 Ubuntu 22.04 的真实服务启停、异常退出租约过期、HTTPS 反向代理和防火墙行为仍需实机验收。 - [!] 主服务端口为非 `443` 时,生成地址包含该主服务端口;高级反向代理模式后续需要明确公开 HTTPS 端口与内部服务端口的独立配置,避免把内部端口写入公开重置地址。 ## 四十四、超级管理员一次性密码重置闭环开发记录(2026-08-27) ### 44.1 本轮需求清单 - [x] 在临时 `/reset` 地址提供中文超级管理员密码重置表单。 - [x] 使用 `Scert-admin` 启动时生成的一次性校验码完成身份校验,并保证校验码只能成功消费一次。 - [x] 校验新密码长度、与超级管理员用户名的关系以及两次输入是否一致。 - [x] 使用 bcrypt 生成新密码摘要,并以原子配置保存方式更新磁盘配置和内存配置。 - [x] 增加 CSRF、同源请求校验、请求体限制和按客户端 IP 的失败频率限制。 - [x] 重置成功后立即关闭当前租约,阻止 `Scert-admin` 刷新已消费的旧租约,并记录数据库审计日志和安全日志。 - [x] 补充安全测试、配置持久化测试、部署说明和跨平台构建复审。 ### 44.2 开发任务状态 - [x] 增加密码规则共享模块,保持首次初始化和密码重置使用同一套规则。 - [x] 增加校验码常量时间比较、会话校验、单次消费和租约刷新终止逻辑。 - [x] 增加密码重置表单渲染、CSRF Cookie、同源校验和请求频率限制。 - [x] 增加超级管理员密码摘要更新、失败回滚边界和一次性入口关闭逻辑。 - [x] 增加审计日志仓储并接入 SQLite、MySQL 5.7 兼容 SQL。 - [x] 补充自动化测试并执行完整复审。 ### 44.3 当前约束 - [!] 当前核心服务仍未完成生产环境真实 HTTPS 终止;本节只完成 `/reset` 应用层安全闭环,不能替代后续 HTTPS 和反向代理实机验收。 - [!] 一次性校验码的受保护本地呈现机制仍需单独实现;在该机制完成前,不将标准输出呈现方式认定为生产可用。 ## 四十五、初始化向导左右分栏视觉优化开发记录(2026-08-27) ### 45.1 本轮需求清单 - [x] 初始化页面保持左右两列主布局,左侧品牌区收窄,右侧配置区加宽。 - [x] 移除左侧品牌区域中的“Scert 证书管理与 Web 服务”和“Scert-admin 手动启动后临时启用 /reset”提示卡,避免在此处重复提示。 - [x] 超级管理员配置表单调整为两列排列,统一视觉节奏。 - [x] 保持初始化配置在前端内存中,只有第 4 步完成初始化时提交后端。 ### 45.2 开发任务状态 - [x] 调整初始化面板最大宽度和左右列比例,避免大屏下界面过度拉伸。 - [x] 保留移动端单列布局,并对 390×844、320×667 视口进行无滚动条检查。 - [x] 保留第 1~4 步“下一步/上一步”流程和字段状态,不改变现有初始化接口。 - [x] 前端生产构建通过。 ### 45.3 本轮验证状态 - [x] 1440×900 桌面视口:主面板宽 1120,左侧约 380,右侧约 738,无页面溢出。 - [x] 390×844 移动视口:页面无横向、纵向滚动条,第 1~4 步卡片均未发现内部溢出。 - [x] 320×667 移动视口:第 4 步页面无横向、纵向滚动条。 - [x] 通过浏览器实际点击验证第 1 步进入第 2 步、第 2 步进入第 3 步,以及返回上一步后已填写字段仍然保留。 - [x] `npm.cmd run build` 通过。 - [x] `git diff --check` 通过。 ### 45.4 当前状态 - [!] 本轮视觉修改已完成,等待用户确认参考效果。 - [!] 当前仅完成初始化向导界面优化,不代表 Scert 完整产品的 ACME/lego 签发、自动续期、远程部署和正式 HTTPS 生产验收已完成。 ## 四十六、全量开发清单阶段复审记录(2026-08-27) ### 46.1 本轮需求清单 - [x] 执行开发清单中当前可以在本机独立完成的代码、测试、构建和安全复审任务。 - [x] 修复 CLI 恢复流程中的备份覆盖、源目标相同、目标类型和失败回滚边界。 - [x] 复审 SQLite 连接可靠性、MySQL DSN 脱敏、证书本地完整性校验和 CLI 备份安全。 - [x] 复审前端目录拆分、用户可见文字和 HTML 实体问题。 - [x] 重新执行后端、前端和 Windows/Linux amd64 构建验证。 - [x] 更新本清单,区分本地复审通过项、已实现但待实机验收项和当前阻塞项。 ### 46.2 本轮开发任务状态 - [x] `backend/internal/cli/operations.go` 的 `restore` 增加恢复输入规范化、当前配置校验、备份数据库普通文件校验、恢复源与目标相同保护、目标类型校验和恢复前备份。 - [x] 恢复 SQLite 数据库失败时,增加配置和数据库的回滚尝试,并返回明确中文错误。 - [x] 恢复文件判断改用不跟随符号链接的普通文件检查,避免把符号链接当作安全恢复目标。 - [x] 补充 CLI 备份、恢复输入、排他复制和路径规范化测试。 - [x] 保留配置和数据库恢复前备份,不覆盖已有备份文件。 - [x] 修复 Dashboard 服务器重载命令占位文本中的 HTML 换行实体,改为普通中文界面可读形式。 - [x] 保留页面公共组件和按页面目录拆分结构:`src/views/components/AccessShell` 与各页面目录分离管理。 ### 46.3 自动化复审结果 - [✓] `go test ./...` 通过。 - [✓] `go test -race ./...` 通过。 - [✓] `go vet ./...` 通过。 - [✓] `go mod verify` 通过。 - [✓] `npm.cmd run build` 通过。 - [✓] Windows amd64、`CGO_ENABLED=0` 的 `review-scert-windows-amd64.exe` 和 `review-scert-admin-windows-amd64.exe` 构建通过。 - [✓] Linux amd64、`CGO_ENABLED=0` 的 `review-scert-linux-amd64` 和 `review-scert-admin-linux-amd64` 构建通过。 - [✓] `git diff --check` 通过。 - [✓] 后端 Go 源码和前端源码未发现中文 HTML 实体、Unicode 转义、乱码或旧重置入口类名。 - [✓] 代码、文档和配置源文件未发现 UTF-8 BOM。 - [✓] Git 差异未发现删除文件或重命名文件;本轮未执行 Git 提交、推送、重置或清理。 - [✓] 新构建产物使用 `review-` 前缀,未覆盖 `build` 目录中已有构建文件。 ### 46.4 已实现但必须继续进行真实环境验收的任务 以下任务已有代码或测试基础,但不能仅凭本机自动化测试标记为复审通过: - [x] `go-acme/lego`、Let’s Encrypt Production/Staging、DNS-01 Provider 和 CNAME 委派的代码接入边界已保留。 - [x] 证书本地文件、私钥匹配、完整证书链、有效期、域名覆盖和 SAN 覆盖校验已实现。 - [x] SSH 私钥加密存储、远程部署工作流、远程证书目录模板和失败回滚的基础能力已实现。 - [x] HTTP 通知、第三方邮件接口配置、事件模式、认证方式、重试和脱敏配置基础能力已实现。 - [x] SQLite、MySQL 5.7 和 MySQL 8.0 的数据访问与迁移分支已保留,SQLite 已通过本地专项验证。 - [x] 需要真实环境继续验证:Let’s Encrypt 申请、各 DNS 服务商 API、CNAME 委派、真实 SSH/SFTP、远程 Windows 10/11、Ubuntu 22.04/24.04、Debian、CentOS/Rocky Linux、Nginx、Caddy、Apache、MySQL 5.7/8.0 实例和云安全组。 - [x] 需要真实环境继续验证:Linux systemd、Windows Service、本机防火墙真实放行、核心 HTTPS 终止、高级反向代理 HTTPS、Wails 桌面版和浏览器视觉验收。 ### 46.5 当前阻塞或未完成任务 - [!] 真实 Let’s Encrypt 和 DNS Provider 连通性未使用用户生产凭据执行,不能宣称证书申请已经成功。 - [!] 真实服务器部署和部署后的公网 HTTPS 在线校验尚未完成,不能宣称多服务器部署已经完成。 - [!] Scert 核心服务生产级 HTTPS 终止、高级反向代理内部 HTTPS 和公开端口独立配置仍需继续开发与实机验证。 - [!] `Scert-admin` 一次性密码重置仍需受保护的本地校验码呈现机制;不能把标准输出中的校验码方式作为生产方案。 - [!] Wails 桌面安装器、Windows Service、Linux systemd 安装和跨平台防火墙适配仍需继续开发或实机验收。 - [!] MySQL 5.7 基础实例连接、MySQL 8.0 兼容迁移和升级回滚尚未完成实机验收。 - [!] 原清单中仍有大量规划阶段 `[ ]` 条目,不能因为局部代码和自动化测试通过而整体改为 `[✓]`。 ### 46.6 复审结论 本轮已完成当前工作区内可以独立验证的开发、修复和自动化复审,后端测试、竞态检查、静态检查、依赖校验、前端构建和双平台 amd64 构建均通过。恢复流程的安全边界已补强,前端源码中的遗留 HTML 实体已处理。 本项目当前结论为:**本地开发复审通过,尚未达到完整产品发布和需求总验收条件**。后续应优先完成真实 ACME/DNS、真实远程部署、正式 HTTPS、认证安全、安装服务、Wails 和 MySQL 双版本实机验收。原有章节中的历史状态和未完成项保留,不进行机械批量改标。 ## 四十七、Lego DNS Provider 集成与离线复审记录(2026-08-28) ### 47.1 本轮需求清单 - [x] 继续使用 `go-acme/lego` 作为 ACME 和 DNS-01 实现。 - [x] 接入第一批已确认的 DNS Provider 工厂。 - [x] 保留 CNAME 委派和其他服务商扩展占位,不虚构尚未完成的适配器。 - [x] 修正旧测试中将阿里云 DNS 错误标记为未开放的问题。 - [x] 单元测试不得因伪造凭据访问真实云 API。 ### 47.2 本轮开发任务状态 - [x] 接入 Cloudflare、阿里云 DNS、DNSPod、华为云、腾讯云、AWS Route 53 和 Google Cloud DNS 的 lego Provider 构造工厂。 - [x] 为新增 lego Provider 补齐 Go 模块依赖和校验和。 - [x] 为已接入 Provider 增加构造级测试。 - [x] 保留 CNAME 委派和其他服务商的类型化未开放错误。 - [x] 华为云测试改为无效区域校验,避免单元测试触发真实鉴权请求。 - [x] Google Cloud 测试使用格式错误的服务账号 JSON 验证已接入且错误可识别。 ### 47.3 本轮验证状态 - [✓] `go test ./internal/dnsprovider` 通过。 - [✓] `go test -race ./internal/dnsprovider` 通过。 - [✓] `go vet ./internal/dnsprovider` 通过。 - [✓] `go test ./...` 通过。 - [✓] `go test -race ./...` 通过。 - [✓] `go vet ./...` 通过。 - [✓] `go mod verify` 通过。 - [✓] `npm.cmd run build` 通过。 - [✓] `git diff --check` 通过;换行格式提示不属于差异错误。 ### 47.4 当前边界 - [x] Provider 工厂和凭据字段映射已完成本地代码级接入,等待真实环境验收。 - [!] 本轮未使用真实 DNS API 凭据,不能将 DNS 权限测试、记录创建清理和证书申请标记为生产验收通过。 - [!] 华为云 lego 构造过程可能在有效凭据下请求项目区域信息,真实测试必须放在集成测试或用户明确授权的环境中。 - [!] CNAME 委派和其他服务商仍属于扩展占位,未接入自动创建、检查和清理流程。 ### 47.5 复审结论 本轮完成了第一批 lego DNS Provider 的工厂接入、依赖锁定和离线测试修正。全量后端测试、竞态检查、静态检查、模块校验和前端构建均通过。真实 DNS 服务商权限、DNS-01 记录生命周期和 Let’s Encrypt 证书签发仍需在受控真实环境中继续验收。 ## 四十八、HTTP 邮件通知会话认证与中文编码修复记录(2026-08-28) ### 48.1 本轮需求清单 - [✓] 使用 UTF-8 编码发送登录请求和邮件通知请求。 - [✓] HTTP 通知请求声明 `application/json; charset=utf-8`。 - [✓] 检查邮件服务统一响应中的 `errorNo`,不能只依据 HTTP 200 判断成功。 - [✓] 会话认证收到 HTTP 401、403 或对应业务错误码时,重试前重新登录。 - [✓] 保留会话认证密码原文,不因校验而修改合法密码内容。 - [✓] 初始化向导支持“账号登录会话”和自定义登录路径。 - [✓] CLI 支持修改 `notification.http_login_path`。 - [✓] 增加中文 UTF-8、业务失败和会话刷新回归测试。 ### 48.2 本轮验证状态 - [✓] `go test ./...` 通过。 - [✓] `go test -race ./...` 通过。 - [✓] `go vet ./...` 通过。 - [✓] `go mod verify` 通过。 - [✓] `npm.cmd run build` 通过。 - [✓] `git diff --check` 通过。 - [!] 临时邮件服务此前由 Windows PowerShell 默认编码发送的旧邮件已经乱码,无法在服务端原地修复;该邮件已保留作为问题记录。 - [✓] 使用明确 UTF-8 请求重新发送唯一测试邮件,并通过邮件列表和详情接口确认标题、纯文本、HTML 正文均为正常中文,状态为成功且错误为空。 - [!] 本轮验证的是临时邮件服务的服务端列表与详情结果,尚未在最终收件邮箱客户端中完成到达、编码和渲染复核。 ### 48.3 复审结论 本轮已完成 HTTP 邮件通知的 UTF-8 编码、业务响应判断、会话失效刷新和配置入口开发,并通过自动化验证;同时已通过临时邮件服务的接口详情确认修复后的中文内容正常。Scert 代码链路已经避免因客户端默认字符集导致的中文乱码,但最终收件邮箱客户端的到达和渲染仍需在发布环境继续复核。 ## 四十九、持续开发复审记录(2026-08-28) ### 49.1 本轮需求清单 - [x] 继续复审上一轮 Ubuntu 模拟测试后的配置、任务、重置地址、安装服务和数据库备份恢复改动。 - [x] 增强 MySQL 5.7/8.0 备份 SQL 的数据字面量和恢复语句拆分兼容性。 - [x] 补充失败证书任务 HTTP 响应的嵌套状态、顶层状态和完成时间断言。 - [x] 补充管理页面域名带路径时的 `/reset` 地址边界测试。 - [x] 复核 systemd 技术文档路径与 Linux 安装脚本复制路径的一致性。 - [x] 执行本地全量自动化验证和 Windows/Linux amd64 交叉构建。 ### 49.2 本轮开发任务状态 - [x] MySQL 备份导出支持 `sql.RawBytes`,并对字符串中的反斜杠、空字节、换行、回车、控制字符和单引号进行 SQL 字面量转义。 - [x] MySQL 恢复语句拆分器保留 `/*!...*/` 和 `/*+...*/` 可执行注释,避免丢失 MySQL 版本条件语句或优化提示。 - [x] 失败证书任务返回 JSON 中的 `task.status`、`task.stage`、`task.message`、完成时间、更新时间与 `task_status` 已增加一致性测试。 - [x] `/reset` 地址生成支持不带协议的域名、完整 URL、IPv4、IPv6、显式端口和附带路径的域名输入。 - [x] systemd unit 使用 ASCII 技术文档文件名,安装脚本保留中文源文档并复制为技术文件名。 ### 49.3 自动化验证状态 - [✓] `go test ./...` 通过。 - [✓] `go test -race ./...` 通过。 - [✓] `go vet ./...` 通过。 - [✓] `go mod verify` 通过。 - [✓] `npm.cmd run build` 通过。 - [✓] Windows amd64 核心服务和 `Scert-admin` 交叉构建通过。 - [✓] Linux amd64 核心服务和 `Scert-admin` 交叉构建通过。 - [✓] `git diff --check` 通过;Git 输出的 LF/CRLF 提示不属于代码差异错误。 - [✓] 源码范围未发现 `acme.sh`、旧的 `super-admin-reset` 或旧独立重置端口配置引用;测试中保留的旧字段字符串仅用于确认配置不会再次写入该字段。 - [✓] 本轮未删除文件,未清理 `.runtime`,未执行 Git 提交、推送、重置或强制操作。 ### 49.4 当前边界和后续验收 - [!] 尚未使用真实 MySQL 5.7 和 MySQL 8.0 实例执行备份、恢复、迁移和回滚;当前结论为代码级和 SQLite 自动化验证通过。 - [!] 尚未在真实 Let’s Encrypt、DNS Provider、远程 SSH/SFTP、Windows 服务器和各类反向代理环境中完成端到端验收。 - [!] 尚未完成生产级 HTTPS 终止、高级代理内部 HTTPS、Wails 桌面安装器、Windows Service 和跨平台防火墙的完整实机验收。 - [!] `Scert-admin` 一次性重置入口仍需受保护的本地校验码呈现机制,不能把标准输出校验码作为生产方案。 ### 49.5 复审结论 本轮可以在本机独立验证的代码修复、测试和构建任务已完成并通过复审。项目仍处于“本地开发复审通过、真实环境和产品级验收未完成”状态,不能据此宣称完整需求已全部交付。 ## 五十、Ubuntu 22.04 服务生命周期复测与重置地址修复记录(2026-08-28) ### 50.1 本轮需求清单 - [✓] 使用 Ubuntu 22.04 测试环境复测 `Scert` 和 `Scert-admin` 的手动启停流程。 - [✓] 确认 `Scert-admin` 不开机自启动、不监听独立 TCP/UDP 端口,只通过 `systemctl start Scert-admin` 和 `systemctl stop Scert-admin` 控制。 - [✓] 确认 `Scert-admin` 启动后 `/reset` 可用,停止后 `/reset` 返回 404。 - [✓] 按已确认规则修复重置地址,不在 `https://域名或IP/reset` 中暴露主服务端口。 - [✓] 同步当前 Linux amd64 构建产物到 Ubuntu 测试机,并保留远程旧二进制备份。 - [✓] 复核本机全量测试、竞态测试、静态检查、模块校验和前端构建。 ### 50.2 Ubuntu 22.04 实测结果 - [✓] 测试环境为 Ubuntu 22.04.5 LTS,systemd 版本为 249.11。 - [✓] `Scert.service` 使用当前构建产物后正常启动并保持 `active` 状态。 - [✓] `Scert-admin.service` 使用当前构建产物后可以手动启动并保持 `active` 状态。 - [✓] `systemctl is-enabled Scert-admin` 返回 `static`,服务未配置 `[Install]` 和 `WantedBy=`,不能纳入开机启动。 - [✓] `ss -lntup` 仅观察到核心 `Scert` 监听 `*:5200`,没有发现 `Scert-admin` 独立监听端口。 - [✓] `Scert-admin` 启动后访问 `/reset` 返回 HTTP 200,页面中文正常显示。 - [✓] `systemctl stop Scert-admin` 后访问 `/reset` 返回 HTTP 404,临时入口已关闭。 - [✓] systemd unit 的 `Documentation` 已同步为 ASCII 技术文档路径,`systemctl show` 不再出现中文路径 URL 警告。 ### 50.3 本轮修复内容 - [✓] `Config.ResetURL()` 现在始终根据管理域名或公网 IP 生成不带端口的 `https://域名或IP/reset` 地址。 - [✓] 保留 IPv4、IPv6、完整 URL、附带路径和显式端口输入的解析能力,但不把输入端口写入公开重置地址。 - [✓] 更新配置、初始化、管理接口和重置控制器相关测试,覆盖不带端口的域名、IPv4、IPv6、完整 URL和附带路径场景。 - [✓] 测试机直接模式使用临时自签名测试证书启动,仅用于本次 HTTPS 服务生命周期验证,不代表生产证书验收。 ### 50.4 自动化验证状态 - [✓] `go test ./...` 通过。 - [✓] `go test -race ./...` 通过。 - [✓] `go vet ./...` 通过。 - [✓] `go mod verify` 通过。 - [✓] `npm.cmd run build` 通过。 - [✓] `git diff --check` 通过;Git 输出的换行格式提示不属于差异错误。 - [✓] Linux amd64 核心服务和 `Scert-admin` 重新构建并在 Ubuntu 22.04 测试机启动验证通过。 ### 50.5 当前边界 - [!] 测试机使用的是临时自签名证书,尚未完成 Let’s Encrypt Production 真实申请、证书链校验和公网域名访问验收。 - [!] 尚未使用真实 DNS API 权限执行 DNS-01 记录创建、传播检测、清理和证书续期。 - [!] 尚未完成真实远程 SSH/SFTP 部署、Nginx reload、部署失败回滚以及 Windows 服务器实测。 - [!] `Scert-admin` 一次性校验码当前仍通过标准输出和 systemd 日志呈现,正式生产前需要替换为受保护的本地呈现机制。 - [!] 当前测试机原有 SQLite 配置未切换为 MySQL,MySQL 5.7 和 8.0 的真实迁移、备份、恢复和回滚仍需单独验收。 ### 50.6 复审结论 Ubuntu 22.04 上的核心服务启动、`Scert-admin` 手动控制、无独立重置端口、`/reset` 入口启停生命周期和当前构建产物验证通过。本轮同时修复了重置地址仍暴露主服务端口的问题。项目仍为“本地代码和受控测试环境复审通过”,真实 ACME、DNS、远程部署、生产 HTTPS、Windows 和 MySQL 双版本验收仍未完成。 ## 五十一、真实环境集成测试记录(2026-08-28) ### 51.1 本轮测试范围 - [x] 使用临时邮件服务执行真实登录和邮件发送接口调用。 - [✓] 在 Ubuntu 22.04 测试机上使用独立 MySQL 数据库执行 Scert 迁移。 - [✓] 在独立 MySQL 数据库中写入中文配置和域名测试数据。 - [✓] 执行 Scert MySQL 备份,检查备份文件权限和内容可恢复性。 - [✓] 将备份恢复到第二个独立 MySQL 数据库,并核对迁移、配置和域名数据。 - [✓] 停止临时 MySQL 测试服务,确认原有 `Scert.service` 和 `5200` 监听不受影响。 ### 51.2 临时邮件服务真实调用结果 - [x] 登录接口返回 HTTP 200,业务错误码为 `0`。 - [x] 邮件发送接口返回 HTTP 200,业务错误码为 `0`。 - [x] 请求使用 UTF-8 中文主题、纯文本正文、HTML 正文和外部收件人。 - [x] 邮件服务实际登录响应只返回会话 Cookie,当前响应未返回 `smail_csrf` Cookie;在本次部署中,携带会话和同源请求头即可完成发送。 - [!] 尚未从外部收件箱客户端确认最终投递、中文显示和邮件状态异步处理结果;API 返回成功只代表邮件已通过接口校验并创建发送任务。 - [!] 需要在正式接入前确认临时服务部署版本是否与 `doc/后端接口说明文档.md` 中的 CSRF 约定一致,并保留无 CSRF Cookie 的兼容行为或补充服务端配置。 测试过程中未将密码、会话 Cookie 或令牌写入 Scert 配置、日志、Git 文件或本任务清单。 ### 51.3 Ubuntu 22.04 MySQL 8.0 真实测试结果 测试机信息: ```text 系统:Ubuntu 22.04.5 LTS MySQL:8.0.46-0ubuntu0.22.04.3 监听端口:3306 连接方式:本机 Unix Socket,使用独立测试数据库 ``` - [✓] 创建独立数据库 `scert_real_test_20260828`,字符集为 `utf8mb4`;未修改原有数据库。 - [✓] 使用当前 Scert 二进制和 MySQL DSN 启动临时服务,应用启动自动完成 1—4 号迁移。 - [✓] 迁移后确认存在 `settings`、`domains`、`tasks`、`audit_logs`、`servers`、`domain_servers`、`task_attempts` 和 `schema_migrations` 表。 - [✓] 写入中文设置项和域名记录,读取结果与写入内容一致。 - [✓] 执行 `scert backup`,生成 `scert.json` 和 `scert.sql` 备份。 - [✓] SQL 备份文件权限为 `600`。 - [✓] 创建第二个独立数据库 `scert_real_restore_20260828`,执行 `scert restore` 后,迁移版本 1—4、中文设置项和域名记录均恢复正确。 - [✓] 临时服务停止后,原有 `Scert.service` 仍为运行状态,原有 `5200` 端口保持监听,临时 `5290` 端口已关闭。 ### 51.4 MySQL 5.7 兼容性状态 - [!] 本轮未找到可安全使用的 MySQL 5.7 实际服务授权账号,未对本机或测试机的 MySQL 5.7 实例进行登录、迁移、备份或恢复操作。 - [✓] 已通过代码级迁移语句兼容性检查;当前实现避免使用 MySQL 5.7 不支持的 `ADD COLUMN IF NOT EXISTS`,并在迁移前查询字段和索引是否存在。 - [!] MySQL 5.7 仍需使用独立测试库完成真实迁移、中文数据、备份、恢复和重复迁移幂等性验证后,才能标记为复审通过。 ### 51.5 DNS、ACME 和远程部署边界 - [!] 当前没有获得可确认的真实测试域名和可执行的 DNS API 凭据,本轮未创建或清理 `_acme-challenge` 记录,未执行 Let’s Encrypt Staging 或 Production 申请。 - [!] 当前未执行真实 SSH/SFTP 证书推送、Nginx/Caddy/Apache reload、失败回滚和部署后公网 HTTPS 校验。 - [!] Ubuntu 测试机本轮使用的临时自签名证书只用于 HTTPS 服务生命周期验证,不能作为 Let’s Encrypt 证书链验收结果。 ### 51.6 本轮复审结论 - [✓] 临时邮件服务的真实登录和发送接口调用通过,Scert 当前 HTTP 通知请求格式与该部署的接口行为兼容。 - [✓] Ubuntu 22.04 + MySQL 8.0 的 Scert 迁移、中文数据读写、备份和恢复通过。 - [x] 外部邮箱最终收件、MySQL 5.7 真实实例、DNS API、Let’s Encrypt、远程服务器部署和多类反向代理仍处于等待真实环境或凭据验证状态。 当前准确结论: ```text Scert 本地代码、Ubuntu 22.04 服务生命周期、HTTP 邮件接口调用和 MySQL 8.0 独立数据库流程已完成验证; 外部邮箱最终投递、MySQL 5.7 实例、DNS/ACME 证书申请、远程部署和生产级跨平台验收仍未完成。 ``` ## 五十二、持续开发:MySQL 恢复失败保护(2026-08-28) ### 52.1 本轮需求清单 - [✓] 复审当前未提交代码,确认不覆盖两个已有补丁文件,不执行文件删除和 Git 操作。 - [✓] 检查 MySQL 备份和恢复流程的失败安全边界。 - [✓] 补充 MySQL 恢复前快照和失败回滚保护。 - [✓] 防止不同数据库类型的备份被错误恢复。 - [✓] 完成 Go、前端和差异检查。 ### 52.2 本轮代码调整 - [✓] MySQL 恢复前在配置的备份目录创建 `scert-before-restore-*` 快照目录。 - [✓] 快照目录权限设置为 `700`,SQL 快照文件权限设置为 `600`。 - [✓] MySQL 恢复失败时自动尝试恢复目标数据库快照。 - [✓] MySQL 数据库回滚失败时,将原始恢复错误和回滚错误同时返回。 - [✓] 配置文件恢复仍保留原有的失败回滚逻辑。 - [✓] SQLite 非内存数据库恢复时强制要求备份目录包含 `scert.db`。 - [✓] 备份配置与当前配置的数据库驱动不一致时拒绝恢复。 ### 52.3 自动化验证 - [✓] `go test ./...` 通过。 - [✓] `go test -race ./...` 通过。 - [✓] `go vet ./...` 通过。 - [✓] `go mod verify` 通过。 - [✓] `npm.cmd run build` 通过。 - [✓] `git diff --check` 通过;仅报告现有 Windows 工作区换行格式提示,没有发现空白错误。 ### 52.4 复审边界 - [!] 本轮未对真实 MySQL 5.7 服务执行故障注入回滚测试,仍需独立测试库和明确授权账号。 - [!] MySQL 恢复快照在恢复成功后保留,后续需要增加备份保留策略和管理员可控清理功能;本轮不自动删除快照。 - [!] DNS/ACME、远程服务器部署、生产 HTTPS、Windows 实机和外部邮箱最终投递仍不属于本轮已完成验收范围。 ### 52.5 本轮复审结论 本轮代码修改已完成并通过现有自动化验证。MySQL 恢复流程现在具备恢复前快照、失败回滚和数据库类型隔离保护;但真实 MySQL 5.7 故障注入以及完整生产环境验收仍保持阻塞状态,不能标记为整体项目完成。 ## 五十三、持续开发:Scert-admin 校验码安全呈现(2026-08-28) ### 53.1 本轮需求清单 - [✓] Scert-admin 不监听独立 TCP/UDP 端口,继续保持手动启动和停止策略。 - [✓] 一次性校验码不得写入标准输出、systemd 日志、配置文件或审计日志。 - [✓] Linux systemd 使用受保护的运行时目录保存一次性校验码。 - [✓] 校验码文件仅允许服务运行用户和 root 读取,并在使用后销毁。 - [✓] 补充服务停止、租约失效、成功消费和文件覆盖保护测试。 - [!] Windows 受 ACL 保护的本地校验码呈现适配仍需单独实现和实机验收。 ### 53.2 本轮代码调整 - [✓] `Scert-admin` 增加 `--code-output` 参数,支持指定一次性校验码文件路径。 - [✓] Linux systemd 默认使用 `/run/scert-admin/reset-code`,并配置 `RuntimeDirectoryMode=0700`。 - [✓] 一次性校验码文件采用排他创建和 `0600` 权限,禁止覆盖已有文件。 - [✓] 状态文件只保存校验码 SHA-256 摘要和校验码文件路径,不保存明文校验码。 - [✓] 服务停止、租约失效、校验码消费成功后自动销毁校验码文件。 - [✓] 命令行只显示重置地址和受保护文件路径,不显示校验码明文。 - [✓] 更新 Linux systemd unit、部署说明和 Scert-admin 运维说明。 ### 53.3 自动化验证 - [✓] Scert-admin 控制器测试通过。 - [✓] 校验码文件权限、内容、消费销毁、租约失效销毁和禁止覆盖测试通过。 - [✓] 命令行输出测试确认不会泄露一次性校验码。 - [✓] systemd unit 测试确认包含受保护运行时目录和 `--code-output` 参数。 ### 53.4 复审边界 - [!] 本轮未在 Ubuntu 22.04 实机上验证 systemd `RuntimeDirectory` 实际权限、root/Scert 读取边界和 journal 输出;需要后续在测试机执行交互式验证。 - [!] Windows 暂使用通用文件实现,尚未切换为 ACL 或命名管道保护方案,不能标记为跨平台安全验收通过。 ### 53.5 本轮复审结论 Scert-admin 的 Linux 代码路径已经不再通过标准输出泄露一次性校验码,默认 systemd 部署改为受保护的 `/run/scert-admin/reset-code` 临时文件,并覆盖了生命周期销毁和命令行输出回归测试。Linux 实机权限边界与 Windows 受保护呈现仍保持待验证状态。 ## 五十四、持续开发:校验码跨平台保护接入复审(2026-08-28) ### 54.1 本轮需求清单 - [✓] 继续保留超级管理员、管理员、普通用户、多角色和权限控制逻辑,不改为单账户模式。 - [✓] 一次性校验码不得写入标准输出、systemd journal、普通配置、审计日志或备份。 - [✓] Linux 使用 `0600` 文件权限和受保护运行时目录保存一次性校验码。 - [✓] Windows 使用当前服务账户、Local System 和本地管理员组构造受保护 ACL。 - [✓] 校验码成功消费、服务停止、租约失效和过期消费时销毁临时文件。 - [✓] 已有校验码文件不得被新的重置会话覆盖。 ### 54.2 代码复审与调整 - [✓] 复审发现 Windows ACL 函数已实现但未接入实际写入流程。 - [✓] `writeCodeFile` 在写入并同步校验码后调用 `protectCodeFile`,保护失败时沿用失败清理逻辑删除临时文件。 - [✓] Windows ACL 使用受保护 DACL,服务账户仅获得读取和删除权限,Local System 与本地管理员组保留管理权限。 - [✓] Linux 路径继续使用 `0600` 权限,不引入不必要的平台特定依赖。 - [✓] 保留排他创建逻辑,避免覆盖已有校验码文件。 ### 54.3 自动化验证 - [✓] `go test ./...` 通过。 - [✓] `go test -race ./...` 通过。 - [✓] `go vet ./...` 通过。 - [✓] `go mod verify` 通过。 - [✓] `GOOS=windows GOARCH=amd64 go build ./internal/admin ./cmd/scert-admin` 通过。 - [✓] `npm.cmd run build` 通过。 - [✓] `git diff --check` 未发现空白错误;换行格式提示属于 Windows 工作区提示。 ### 54.4 复审边界 - [!] 尚未在真实 Windows 服务账户环境中验证 ACL 的实际读取、删除和拒绝其他账户读取效果。 - [!] 尚未在 Ubuntu 22.04 实机中再次验证 systemd 运行时目录权限、journal 内容和停止服务后的文件销毁。 - [!] 真实 ACME/DNS API、远程 SSH 部署、Nginx/Caddy/Apache、生产 HTTPS 和外部邮箱最终投递仍不属于本轮已完成验收范围。 ### 54.5 本轮复审结论 Windows ACL 保护现在已经接入一次性校验码实际写入流程,失败会自动清理临时文件;Linux 文件权限和生命周期销毁逻辑保持通过。自动化构建与测试通过,但 Windows 权限实测和 Ubuntu 22.04 systemd 实机复审仍需单独完成,不能将跨平台生产安全验收标记为已完成。 ## 五十五、Ubuntu 22.04 实机复审:Scert-admin 受保护校验码(2026-08-28) ### 55.1 测试范围 - [✓] 在 Ubuntu 22.04.5 LTS 测试机 `192.168.2.3` 上部署本轮 Linux amd64 `Scert-admin` 构建产物。 - [✓] 部署本轮 `Scert-admin.service`,执行 `systemctl daemon-reload` 和 `systemd-analyze verify`。 - [✓] 测试机原有 `Scert-admin` 二进制和 unit 已创建带时间戳的 `/tmp` 备份,未删除原文件。 - [✓] 验证手动启停、运行时目录权限、校验码文件权限、日志泄露、网络监听和停止后销毁行为。 ### 55.2 实机验证结果 - [✓] `systemctl is-enabled Scert-admin` 返回 `static`,没有开机自启动注册。 - [✓] `systemctl start Scert-admin` 后服务状态为 `active`。 - [✓] `/run/scert-admin` 实际权限为 `700`,所有者为 `Scert:Scert`。 - [✓] `/run/scert-admin/reset-code` 实际权限为 `600`,所有者为 `Scert:Scert`。 - [✓] 本次新版服务启动后的最近日志未发现校验码明文。 - [✓] 未发现 `Scert-admin` 独立 TCP/UDP 网络监听;核心服务继续使用既有 `5200` 监听。 - [✓] `systemctl stop Scert-admin` 后服务变为 `inactive`,校验码文件和运行时目录均被清理。 ### 55.3 测试机历史遗留说明 - [!] 测试机旧版服务在本次升级前的历史 journal 中曾保存过明文校验码;这属于旧版本遗留日志,不能通过本轮代码自动消除。 - [!] 生产升级前应根据组织日志保留策略处理旧 journal,并确保升级后的服务不再写入明文校验码。 - [!] `systemd-analyze verify` 同时报告了测试机其他 `snapd.service` 的未知配置项警告,与 Scert unit 无关;Scert unit 本身未产生语法错误。 ### 55.4 当前复审结论 Linux Ubuntu 22.04 上的 `Scert-admin` 手动启停、无开机自启动、无独立网络监听、受保护运行时目录、校验码权限、日志不泄露和停止后销毁均已完成实机验证。Windows ACL 仍只完成代码接入、自动化交叉编译和静态复审,尚未完成 Windows 服务账户权限实测,因此整体跨平台安全验收仍不能标记为完成。 ## 五十六、真实 ACME/DNS 测试:阿里云 DNS 与 Let’s Encrypt(2026-08-28) ### 56.1 测试范围 - [✓] 使用项目现有 `go-acme/lego` 实现进行 DNS-01 验证。 - [✓] 使用阿里云 DNS Provider 验证 RAM 凭据和 DNS 记录操作权限。 - [✓] 测试域名 `salg.cn` 的 DNS TXT 记录创建、传播检查和清理。 - [!] 测试域名 `zhuguang.asia` 暂未申请证书,不修改其现有 DNS 配置。 - [✓] 证书申请使用独立临时进程和内存密钥,不写入 Scert 证书目录、配置、数据库或备份。 ### 56.2 代码修正 - [✓] 修正 `backend/internal/certificate/lego.go`:ACME 账户邮箱仅用于账户注册,不再写入证书 CSR 的 `EmailAddresses` 字段。 - [✓] 修正后通过 Let’s Encrypt Staging 的证书申请验证,确认不再触发 `CSR contains one or more email address fields` 错误。 ### 56.3 实测结果 - [✓] `salg.cn` 阿里云 DNS API 测试成功,临时 `_acme-challenge` TXT 记录能够创建和清理。 - [✓] `salg.cn` Let’s Encrypt Staging DNS-01 验证成功。 - [✓] `salg.cn` Let’s Encrypt Staging 证书签发成功。 - [✓] Staging 证书域名匹配成功,证书与私钥匹配成功。 - [✓] Staging 证书链解析成功,共解析到 5 张证书。 - [✓] Staging 证书有效期为 2026-08-28T15:49:14Z 至 2026-11-26T15:49:13Z。 - [✓] 通过阿里云 DNS API 查询确认测试结束后 `_acme-challenge.salg.cn` TXT 记录数为 0。 - [✓] `go test ./...`、`go vet ./...`、`go mod verify` 和 `npm.cmd run build` 全部通过。 ### 56.4 `zhuguang.asia` 阻塞原因 - [!] `_acme-challenge.zhuguang.asia` 当前存在 CNAME 委派,目标为 `expired.hichina.com`。 - [!] 阿里云 Provider 按 CNAME 委派查找目标 DNS 区域时,无法在当前阿里云账号中找到 `expired.hichina.com` 托管区域。 - [!] 在用户修正或确认该 CNAME 委派前,不执行自动删除、替换或新增 DNS 记录。 ### 56.5 Production 实测边界 - [!] `salg.cn` Production 申请已发起,但因递归 DNS 服务器在传播窗口内仍返回此前测试的旧 TXT 值,未能完成本次验证。 - [✓] Production 失败后 lego 已执行 DNS-01 清理和授权停用,没有留下运行中的申请任务。 - [!] 该失败暴露出 DNS 删除/新增后的缓存传播窗口约为 600 秒;后续应在生产流程中支持可配置传播等待时间、重试策略和失败后的明确诊断。 - [!] 本轮未将生产证书保存到 Scert 默认目录,也未执行远程服务器部署或修改 Nginx、Caddy、Apache 配置。 ### 56.6 本轮复审结论 阿里云 DNS Provider 的 RAM 权限、`salg.cn` 的 DNS-01 验证、lego Staging 证书申请、证书解析、域名匹配、私钥匹配和清理流程已完成真实验证。当前需要后续处理的事项为:修正 `zhuguang.asia` 的 CNAME 委派,以及在 DNS 传播延迟场景下完善 Production 申请的等待和重试策略。Production 证书签发、证书落盘、自动续期、远程部署和线上 HTTPS 校验仍不能标记为整体完成。 ## 五十七、DNS-01 传播等待与诊断配置(2026-08-29) ### 57.1 需求清单 - [✓] 为 DNS-01 增加可配置的最大传播等待时间。 - [✓] 为 DNS-01 增加可配置的传播检测间隔。 - [✓] 保留旧配置兼容性,读取缺少新字段的配置时自动补齐默认值。 - [✓] 对等待时间和检测间隔增加范围校验,避免无效参数进入证书申请流程。 - [✓] 证书申请失败时输出本次使用的传播等待参数,便于诊断 DNS 缓存传播延迟。 ### 57.2 实现清单 - [✓] 在 `ACMEConfig` 中增加 `propagation_timeout_secs`,默认值为 900 秒。 - [✓] 在 `ACMEConfig` 中增加 `propagation_polling_interval_secs`,默认值为 10 秒。 - [✓] 通过 `challenge.ProviderTimeout` 包装实际 DNS Provider,并注入 `go-acme/lego`。 - [✓] 在 `scert config set` 支持修改上述两个配置项。 - [✓] 增加默认值、旧配置归一化、范围校验和保存加载测试。 - [✓] 增加 Provider 操作转发、参数读取、无效参数保护和空 Provider 测试。 - [✓] 保持敏感 DNS 凭据仅在调用时解密,未改变明文配置阶段和加密持久化策略。 ### 57.3 参数规则 | 配置项 | 默认值 | 允许范围 | 说明 | |---|---:|---:|---| | `acme.propagation_timeout_secs` | 900 秒 | 1 至 86400 秒 | DNS 记录发布后,lego 等待验证传播的最长时间 | | `acme.propagation_polling_interval_secs` | 10 秒 | 大于 0 且不大于等待时间 | lego 检查 DNS 记录传播状态的间隔 | ### 57.4 验证结果 - [✓] `go test -race ./...` 通过。 - [✓] `go vet ./...` 通过。 - [✓] `go mod verify` 通过。 - [✓] 前端生产构建通过。 - [✓] `git diff --check` 通过。 ### 57.5 当前边界 - [!] 配置已接入真实 lego DNS-01 流程,但仍需使用真实 DNS Provider 和 Let's Encrypt Production 在公网传播延迟场景完成最终验收。 - [!] 本轮未修改远程服务器部署、Nginx、Caddy、Apache 或证书文件替换逻辑。 ## 五十八、Web 初始化接入 DNS-01 传播等待配置(2026-08-29) ### 58.1 本轮需求清单 - [✓] Web 初始化向导可以配置 DNS-01 最大传播等待时间。 - [✓] Web 初始化向导可以配置 DNS-01 传播检测间隔。 - [✓] Web 表单显示默认值:最大等待 900 秒、检测间隔 10 秒。 - [✓] 前端阻止小于 1 秒、超过 86400 秒或检测间隔大于最大等待时间的输入。 - [✓] 配置完成前参数只保留在向导内存,提交时由后端统一校验并保存。 - [✓] 兼容未提交这两个字段的旧调用,后端沿用配置默认值。 ### 58.2 代码调整 - [✓] `backend/internal/httpapi/setup.go` 接收并返回两个 DNS 传播配置字段。 - [✓] `backend/internal/setup/setup.go` 将 Web 初始化请求写入 `ACMEConfig`,保留零值缺省兼容行为。 - [✓] `frontend/src/views/SetupWizard/SetupWizard.js` 增加表单状态、前端校验和提交字段。 - [✓] `frontend/src/views/SetupWizard/SetupWizard.vue` 在 DNS 验证步骤增加两个中文配置项及说明。 - [✓] 保持页面相关文件按 `src/views/SetupWizard/` 目录集中管理。 ### 58.3 自动化验证 - [✓] 增加初始化层的非法传播参数回归测试。 - [✓] 增加 Web 初始化接口保存传播参数回归测试。 - [✓] `go test -race ./...` 通过。 - [✓] `go vet ./...` 通过。 - [✓] `go mod verify` 通过。 - [✓] `npm.cmd run build` 通过。 - [✓] `git diff --check` 通过。 - [✓] 目标代码范围未发现连续问号、替换字符或错误换行标记。 ### 58.4 复审边界 - [!] 本轮未使用浏览器 MCP 进行页面截图验收;本轮目标是配置链路接入,不包含布局和视觉改版。 - [!] 真实 DNS Provider、Let's Encrypt Production 公网传播延迟和生产续期仍需在授权环境完成最终验收。 - [!] 本轮未执行 Git 提交、推送、文件清理或删除。 ## 五十九、初始化向导通知布局与敏感凭据交互优化(2026-08-29) ### 59.1 需求清单 - [x] 初始化向导第二步按服务配置、认证配置、敏感凭据、收发件人和投递策略分组显示。 - [x] HTTP 通知的 Token、HMAC 密钥和会话凭据支持配置时明文查看与隐藏切换。 - [x] 配置提交后由后端加密保存敏感凭据,普通配置文件不保存明文密钥。 - [x] DNS 凭据字段使用不同的动态 ID,避免模板静态检查发现重复 ID。 - [x] 页面显示文字保持中文,源码范围未发现 HTML 编码中文和替换字符。 ### 59.2 实现与验证清单 - [x] 完成 `SetupWizard.vue` 中 DNS 普通凭据输入框动态 ID 修正。 - [x] 完成前端生产构建验证:`npm.cmd run build`。 - [x] 完成后端竞态测试:`go test -race ./...`。 - [x] 完成后端静态检查:`go vet ./...`。 - [x] 完成 Go 模块完整性检查:`go mod verify`。 - [x] 完成 Git 差异格式检查:`git diff --check`。 - [!] 浏览器 MCP 因共享 Chrome Profile 已被其他浏览器进程占用,本轮未完成真实截图验收;未强制关闭用户浏览器。 - [!] 低高度桌面窗口下的初始化向导最终视觉效果仍需在 MCP 可用后复测。 ### 59.3 当前状态 本轮代码调整和自动化检查已完成,相关任务标记为“已完成,等待复审”。浏览器 MCP 视觉验收属于外部运行环境阻塞,不影响前端构建和后端自动化检查结果;待独立浏览器窗口可用后,再对桌面宽屏、中等窗口和低高度窗口进行实际显示复审。 ## 六十、SSH 密钥配置引导与最新测试范围更新(2026-08-29) ### 60.1 需求清单 - [x] 记录最新阿里云 RAM 测试授权域名:`epwn.uno`、`zedyj.cn`、`szqh.uno`。 - [x] 将 `192.168.2.4` 加入 SSH 推送测试范围,并保留 `192.168.2.3`。 - [x] 为 SSH 密钥配置增加 Windows、Linux/macOS 生成命令引导。 - [x] 增加公钥安装位置和安装命令说明。 - [x] 增加复制密钥生成命令和公钥安装命令功能。 - [x] 增加本机私钥文件导入功能,导入内容只进入当前页面内存。 - [x] 增加私钥口令显示/隐藏功能,并保持后端加密存储约束。 - [x] 保持 SSH 主机 SHA256 指纹校验和私钥不回显策略。 ### 60.2 实现文件 - `frontend/src/views/Dashboard/Dashboard.js` - 增加 SSH 平台切换、命令模板、剪贴板复制和本机私钥文件读取逻辑。 - `frontend/src/views/Dashboard/Dashboard.vue` - 增加 SSH 三步配置引导、平台选择、命令复制、私钥文件导入和口令显示控制。 - `frontend/src/views/Dashboard/Dashboard.css` - 增加引导卡片、步骤布局、命令卡片、平台标签和文件选择控件样式。 - `doc/SSH密钥配置指南.md` - 增加用户可直接照做的 Windows、Linux/macOS、Linux 服务器和 Windows OpenSSH 配置说明。 ### 60.3 待验证任务 - [ ] 使用最新授权域名完成阿里云 DNS API 读取边界验证,不记录或输出敏感凭据。 - [ ] 在 `192.168.2.3` 上完成 SSH 连接、证书文件推送和网站服务重载测试。 - [ ] 在 `192.168.2.4` 上完成 SSH 连接、证书文件推送和网站服务重载测试。 - [ ] 完成前端生产构建、后端竞态测试、静态检查和模块完整性检查。 - [ ] 在独立浏览器 MCP 窗口中完成桌面端页面截图复审。 - [!] 移动端视觉复审按规则使用 Mobile Preview 插件,不在本轮启动浏览器 MCP 移动端预览。 ### 60.4 安全边界 - 不把阿里云 RAM 凭据、SSH 私钥、服务器密码写入代码、文档、普通配置或 Git。 - 不把测试服务器地址硬编码到生产配置。 - 不覆盖远程服务器已有授权公钥,只允许追加或由用户明确维护授权文件。 - SSH 连接仍必须校验主机 SHA256 指纹。 ### 60.5 本轮验证结果 - [x] `npm.cmd run build` 通过,前端生产构建成功。 - [x] `go test -race ./...` 通过。 - [x] `go vet ./...` 通过。 - [x] `go mod verify` 通过,所有模块已验证。 - [x] `git diff --check` 通过。 - [x] 本机前端 `127.0.0.1:5273` 返回 HTTP 200。 - [x] Scert 后端 `127.0.0.1:5200/healthz` 返回 HTTP 200,健康状态正常。 - [x] `192.168.2.3:22` 和 `192.168.2.4:22` TCP 可达。 - [!] 尚未执行两台测试机的 SSH 登录、证书推送和网站服务重载;需要分别配置并核对私钥和主机指纹。 - [!] 浏览器 MCP 默认共享 Profile 仍被其他浏览器进程占用,本轮未强制关闭现有浏览器,未完成真实截图复审。 ### 60.6 复审状态 - `[x]` 源码和文档修改完成,等待用户复审。 - `[x]` 自动化构建和后端检查完成,等待用户复审。 - `[!]` 真实 SSH 推送、DNS API 在线验证和浏览器截图复审仍待独立测试条件满足后执行。 ## 六十一、最新授权域名 DNS API 在线测试(2026-08-29) ### 61.1 测试范围 - [x] 使用当前源码启动独立测试实例,监听 `127.0.0.1:5201`,避免影响仍在运行的 `5200` 旧版本实例。 - [x] 使用阿里云 RAM 测试账号验证 `epwn.uno` 的 DNS API 操作能力。 - [x] 使用阿里云 RAM 测试账号验证 `zedyj.cn` 的 DNS API 操作能力。 - [x] 使用阿里云 RAM 测试账号验证 `szqh.uno` 的 DNS API 操作能力。 - [x] 不申请证书,仅通过测试接口创建并清理临时 DNS-01 验证记录。 ### 61.2 测试结果 | 测试域名 | 测试接口结果 | 结论 | |---|---:|---| | `epwn.uno` | HTTP 200,验证通过 | 阿里云 DNS API 可用 | | `zedyj.cn` | HTTP 200,验证通过 | 阿里云 DNS API 可用 | | `szqh.uno` | HTTP 200,验证通过 | 阿里云 DNS API 可用 | - [x] 当前源码 DNS Provider 列表中,阿里云 DNS 显示为可用。 - [x] 三个域名均完成临时记录创建和自动清理流程。 - [x] 测试实例配置文件中未发现明文 AccessKeySecret。 - [x] 未将任何 AccessKey、Secret 或测试凭据写入代码、文档或 Git。 ### 61.3 其他运行状态 - [x] `http://127.0.0.1:5201/healthz` 返回 HTTP 200。 - [x] 原有 `http://127.0.0.1:5200/healthz` 返回 HTTP 200;该端口当前仍运行旧构建,不用于本轮源码 Provider 结论。 - [x] 前端 `http://127.0.0.1:5273/` 返回 HTTP 200。 - [x] `192.168.2.3:22` TCP 可达。 - [x] `192.168.2.4:22` TCP 可达。 ### 61.4 尚未执行项目 - [!] 尚未进行两台服务器的 SSH 私钥登录;当前缺少可用于测试的私钥和已核对的主机指纹。 - [!] 尚未向两台服务器推送证书或执行 Nginx、Caddy、Apache 服务重载。 - [!] 浏览器 MCP 共享 Chrome Profile 仍被其他浏览器进程占用,尚未完成桌面端真实截图复审。 - [!] 移动端视觉测试仍按规则保留给 Mobile Preview 插件,本轮未启动浏览器 MCP 移动端预览。 ### 61.5 本轮复审结论 - `[x]` 阿里云 RAM 对三个最新授权根域名的 DNS-01 临时记录操作已完成真实验证。 - `[x]` 当前源码中的阿里云 Provider 已确认不是旧版本的“未实现”状态。 - `[!]` DNS API 验证通过不等同于生产证书签发、远程部署和线上 HTTPS 校验完成;后续仍需在明确 SSH 私钥和主机指纹后执行分阶段部署测试。 ## 六十二、绑定邮箱完整地址识别修复(2026-08-29) ### 62.1 用户反馈 - [x] 绑定邮箱输入框不再显示具体邮箱用户名示例。 - [x] 输入完整邮箱地址时,自动识别 `@` 后的邮箱域名。 - [x] 输入框只显示 `@` 前的邮箱名称,下拉列表显示对应常用邮箱后缀。 - [x] 输入到 `@` 但尚未输入域名时,暂时保留当前输入,避免受控输入框重绘导致光标跳动和内容错乱。 ### 62.2 修改文件 - `frontend/src/views/SetupWizard/SetupWizard.vue` - 将绑定邮箱占位文字改为通用提示“请输入邮箱名称”。 - `frontend/src/views/SetupWizard/SetupWizard.js` - 完整邮箱输入时拆分本地部分和域名。 - 常用域名自动选中对应下拉项。 - 非常用域名自动归入“自定义后缀”。 - 保留完整邮箱到提交数据中的 `admin_email` 字段。 ### 62.3 验证结果 - [x] 前端生产构建通过。 - [x] 源码中未发现 `likb_blue` 等具体邮箱示例。 - [x] 源码中未发现 HTML 数字编码中文字符。 - [x] `git diff --check` 通过。 - [!] 浏览器 MCP 当前因共享 Chrome Profile 被其他浏览器进程占用,暂未完成本次实际输入交互截图复审。 ## 六十三、初始化向导布局与 DNS API 在线测试完善(2026-08-29) ### 63.1 本轮需求 - [✓] 将 Scert 主服务端口放入初始化向导第 1 步。 - [✓] 将管理页面使用的域名或公网 IP 放入初始化向导第 1 步。 - [✓] 补全 DNS API 在线测试的临时 TXT 记录创建、公网 DNS 查询确认和自动清理流程。 - [✓] 在前端展示 DNS 在线测试的创建、查询和清理阶段状态及诊断信息。 ### 63.2 细节修复 - [✓] 将“管理页面访问方式”从嵌套 `label` 调整为独立可访问性控件,避免按钮名称错误继承外层字段标题。 - [✓] 为域名/IP切换按钮补充 `aria-pressed` 状态。 - [✓] 将 DNS 验证兜底错误改为中文提示“DNS API 在线验证失败”。 ### 63.3 验证状态 - [✓] 后端单元测试、竞态测试、静态检查和模块校验通过。 - [✓] 前端生产构建通过。 - [✓] 无效 DNS 凭据测试能够展示“创建记录:失败”阶段诊断,未暴露 TXT 验证值或凭据。 - [✓] 桌面浏览器已完成 1440×900、1200×700 宽度/低高度复审,内容区可滚动且底部操作栏保持可见。 - [!] 真实 DNS 服务商成功链路不能在无用户授权凭据和测试域名时重复执行;现有真实验证记录仍以此前授权测试结果为准。 ## 六十四、临时文件清理与 DNS 在线测试取消场景保护(2026-08-29) ### 64.1 文件清理 - [✓] 删除根目录已确认无用的 `.codex-*` 临时补丁和临时源码副本。 - [✓] 删除 `.review-reset-docs.patch`、`backend/codex-restore.patch` 和 `backend/.codex-test-build/`。 - [✓] 未删除源码、文档、配置、数据库、证书、运行数据、依赖目录或可能正在使用的构建产物。 - [✓] 清理后确认工作区中未残留上述 Codex 临时文件。 ### 64.2 DNS 在线测试保护 - [✓] 公网 DNS 查询失败或请求被取消后,仍使用独立清理上下文尝试删除临时 TXT 记录。 - [✓] 清理上下文最多保留 30 秒,避免继承已取消的请求上下文,也避免清理操作无限等待。 - [✓] 增加查询取消后自动清理的回归测试。 - [✓] 增加查询失败且自动清理失败时的组合诊断和阶段报告回归测试。 - [✓] 修复 DNS 测试辅助代码中的连续问号占位错误,恢复可读的中文诊断。 ### 64.3 验证结果 - [✓] DNS Provider 定向测试通过。 - [✓] `go test -race ./...` 通过。 - [✓] `go vet ./...` 通过。 - [✓] `go mod verify` 通过。 - [✓] `npm.cmd run build` 通过。 - [✓] `git diff --check` 通过;Git 的换行格式提示不属于差异错误。 - [✓] 跟踪中的源码和文档未发现连续问号、替换字符或 HTML 数字编码中文。 - [!] 本轮未重复使用真实 DNS 凭据写入公网记录;真实服务商成功链路继续沿用此前授权测试结果。 ## 六十五、管理后台登录态门禁接入(2026-08-29) ### 65.1 本轮需求清单 - [✓] 初始化完成后,前端先读取服务端登录会话,再决定显示管理后台或登录页面。 - [✓] 未登录访问根路径时显示管理员登录界面,不再把管理接口 401 错误误报为核心服务连接失败。 - [✓] 初始化向导完成后进入登录状态检查,避免初始化完成后直接渲染未授权管理后台。 - [✓] 登录态检查请求显式携带 Cookie,并保留后端会话过期后的重新登录入口。 ### 65.2 修改文件 - `frontend/src/App.js` - 增加初始化完成后的 `/api/v1/auth/session` 会话检查。 - 区分未登录、已登录和服务检查失败状态。 - 初始化向导完成后将管理后台置为未登录状态。 - `frontend/src/App.vue` - 未登录时渲染管理员登录页面。 - 只有确认已登录后才渲染管理后台。 - `frontend/src/views/Dashboard/Dashboard.js` - 管理接口统一携带登录 Cookie。 - 会话过期时跳转到管理员登录页面,并显示重新登录提示。 ### 65.3 验证状态 - [✓] 前端生产构建。 - [✓] 后端回归测试、竞态测试、静态检查和模块完整性检查。 - [x] 通过浏览器隔离模拟已初始化且未登录场景,根路径显示管理员登录页面,未直接渲染管理数据。 - [x] 通过浏览器隔离模拟已初始化且已登录场景,根路径显示管理后台并完成空数据状态加载。 - [x] 当前管理后台会话过期时跳转管理员登录页面,并提示重新登录。 - [!] 当前运行配置仍未完成首次初始化,尚未在真实已初始化运行数据上重复执行登录流程;隔离模拟不替代生产验收。 - [!] 真实浏览器截图复审仍需独立浏览器 MCP 窗口;不能用移动端预览替代桌面端复审。 ## 六十六、CNAME 委派与凭据规范化完成记录(2026-08-29) ### 66.1 开发任务状态 - [✓] CNAME Provider 标记为可用,并支持配置专用验证域。 - [✓] CNAME 委派支持选择已接入的目标 DNS Provider。 - [✓] CNAME 委派支持嵌套 JSON 凭据,并复用目标 Provider 的凭据校验和 lego 适配器。 - [✓] DNS-01 临时 TXT 记录的创建和清理转发到专用验证域。 - [✓] 委派目标禁止再次选择 CNAME 或其他未接入 Provider,避免递归和不明确的适配器行为。 - [✓] 初始化保存 DNS 凭据前复制并规范化键和值,不修改调用方输入。 - [✓] 增加委派转发、错误透传、递归保护、凭据 JSON 校验和凭据规范化测试。 ### 66.2 验证状态 - [✓] `go test ./...` 通过。 - [ ] `go test -race ./...`、`go vet ./...`、`go mod verify` 和前端生产构建等待本轮最终复核。 - [!] 未使用真实 DNS 凭据执行公网 CNAME、TXT 传播和 Let’s Encrypt Production 验收;该项必须在用户授权的真实域名环境执行。 ## 六十七、全量代码复审与最终验证记录(2026-08-29) ### 67.1 本轮需求与开发状态 - [✓] 系统设置页面补充服务监听地址、服务端口、HTTPS 模式、管理页面域名和管理页面公网 IP。 - [✓] 初始化向导保留首次运行所需的端口和 Web 访问方式配置,并与服务端配置字段保持一致。 - [✓] DNS API 在线测试支持服务商目录、动态凭据字段、CNAME 委派专用验证域、目标 Provider 和嵌套凭据 JSON。 - [✓] DNS 在线测试覆盖临时 TXT 记录创建、公网查询、自动清理和失败阶段报告。 - [✓] CNAME 委派 Provider 已接入,目标 Provider 禁止再次选择 CNAME 或未接入 Provider。 - [✓] DNS 凭据在验证前规范化并在验证成功后加密保存,普通配置和接口响应不返回明文凭据。 - [✓] 设置接口仅在监听地址、服务端口或 HTTPS 模式变化时返回 `restart_required: true`。 - [✓] 手动续期检查接口已接入管理后台。 ### 67.2 实际浏览器和接口复核 - [✓] 当前源码后端已重新构建并启动于 `127.0.0.1:5200`。 - [✓] 前端开发服务运行于 `127.0.0.1:5273`,独立 Chrome DevTools 页面可正常访问。 - [✓] 初始化向导第 1 步实际显示 Scert 主服务端口、管理页面域名/IP 切换和密码重置地址预览。 - [✓] DNS Provider 实际显示“CNAME 委派”,不再显示“适配器待开放”。 - [✓] 选择 CNAME 委派后实际显示专用验证域、委派目标 DNS 服务商和委派凭据 JSON 字段。 - [✓] 使用伪造 Cloudflare 凭据实际触发在线测试,页面显示“创建记录:失败”,未误报验证成功。 - [✓] 设置和初始化接口实际返回服务端口、Web 域名/IP、传播参数和 DNS Provider 状态。 ### 67.3 最终自动化验证 - [✓] `go test ./...` - [✓] `go test -race ./...` - [✓] `go vet ./...` - [✓] `go mod verify` - [✓] `npm.cmd run build` - [✓] `git diff --check` ### 67.4 文件清理与验收边界 - [✓] 根目录没有发现 `.codex` 目录或已知 Codex 临时源码副本。 - [!] `.runtime` 中仍有 3 个已确认的 Codex 临时补丁文件;本轮逐个删除命令被当前执行环境安全策略拒绝,因此未绕过策略强制删除。 - [✓] 未删除源码、文档、配置、数据库、证书、密钥、运行目录或构建产物。 - [!] 未在本轮使用新的真实 DNS 凭据、Let’s Encrypt Production、SSH 私钥、远程服务器或生产 HTTPS 环境;这些仍需用户授权后的实机验收。 - [✓] 代码层开发和本地验证完成,Git 提交与推送仍未执行。 ## 六十八、部署脚本、发布构建与通知安全复核(2026-08-30) ### 68.1 本轮需求清单 - [✓] 增加 Windows 安装器,检查平台、管理员权限、安装产物、服务名称和系统工具。 - [✓] Windows 安装器创建程序、配置、数据、日志、备份、文档、运行时和证书目录。 - [✓] Windows 安装器使用 `LocalService` 注册 `Scert` 和手动启动的 `Scert-admin`,并设置 ACL。 - [✓] Windows 安装器不启动服务、不创建公网防火墙规则、不删除已有配置、数据库、证书和备份。 - [✓] 增加 Windows amd64 和 Linux amd64 的跨平台发布构建脚本。 - [✓] 发布构建输出核心服务、密码重置程序和 SHA-256 校验清单。 - [✓] 通知会话认证保留密码原始字节,不对密码使用 `TrimSpace`;登录业务错误解析 `errorNo`,并保留非敏感错误说明。 - [✓] 通知发送接口仍按“进入邮件服务队列”处理,不将 HTTP 成功误称为最终收件成功。 ### 68.2 新增和修改文件 - `deploy/install-windows.ps1` - `deploy/README.md` - `build/build-release.ps1` - `build/README.md` - `backend/internal/notification/service.go` - `backend/internal/notification/service_test.go` ### 68.3 验证边界 - [x] Windows 安装脚本已完成代码编写,等待 Windows 管理员权限、服务控制台和 ACL 实机复审。 - [x] 发布构建脚本已完成代码编写,等待本轮执行 Windows/Linux 目标构建。 - [x] 通知会话流程已完成本地测试覆盖,真实临时邮箱最终投递仍需查看邮件详情状态和收件证据。 - [!] 未使用真实 DNS 凭据、Let’s Encrypt Production、SSH 私钥、远程服务器或生产 HTTPS 环境;这些项目仍需用户授权后的实机验收。 ## 六十九、SSH 密钥随机路径与配置引导复核(2026-08-30) ### 69.1 本轮需求与实现状态 - [✓] 本机 SSH 密钥统一使用 `/ssl/ssh/` 目录生成。 - [✓] 密钥文件名使用 `用户名+scert-随机标识` 格式,公钥最终保存为不带 `.pub` 后缀的文件。 - [✓] 每次打开 SSH 密钥配置弹窗都会重新生成随机标识,避免不同主机或不同配置复用固定文件名。 - [✓] Windows、Linux/macOS 密钥生成命令会临时产生 `.pub` 文件,随后移动为当前随机路径对应的不带 `.pub` 后缀的公钥文件,安装命令统一使用该最终路径。 - [✓] 页面显示本次密钥文件名、本地私钥路径、本地公钥路径和远程登录目标。 - [✓] Scert 后端仍仅保存加密敏感信息引用,不将本地明文私钥路径或私钥内容写入普通配置。 ### 69.2 本轮验证结果 - [✓] `npm.cmd run build` 通过。 - [✓] 浏览器复核首次打开和再次打开弹窗时随机文件名发生变化。 - [✓] 浏览器复核服务器配置填写 `deploy` 和 `192.0.2.50` 后,路径和 SSH 目标同步更新。 - [✓] 浏览器复核 Windows 与 Linux/macOS 命令均包含当前随机路径和最终公钥路径;生成命令包含临时 `.pub` 文件移动步骤。 - [✓] 桌面端 1440×901 视口下弹窗宽度为 1080px,页面背景滚动已锁定,弹窗内部无垂直溢出。 - [!] 真实 SSH 主机、公钥安装、私钥登录和证书部署仍需用户提供并授权实机环境后验收。 ## 七十、证书目录结构合并与当前版本简化(2026-08-30) ### 70.1 本轮需求清单 - [✓] 合并生产和开发证书目录层级,申请环境继续由域名配置中的 ACME 环境字段区分。 - [✓] 合并当前和历史版本目录层级,正式证书目录只保留当前使用版本。 - [✓] 版本目录名称改为 `YYYYMMDD-Vx.x`,例如 `20260830-V1.0`。 - [✓] 同一天重复保存时递增版本号,避免目录覆盖。 - [✓] 保留备份目录用于保存失败回滚所需的旧证书文件,不将备份目录作为历史版本列表。 - [✓] 前端移除历史版本查看和恢复入口,只显示当前证书状态。 ### 70.2 代码和文档调整 - `backend/internal/certificate/lifecycle.go` - `backend/internal/certificate/lifecycle_version_test.go` - `backend/internal/certificate/service_test.go` - `frontend/src/views/Dashboard/Dashboard.vue` - `frontend/src/views/Dashboard/Dashboard.js` - `frontend/src/views/Dashboard/Dashboard.css` - `doc/SSL服务程序需求确认文档.md` - `doc/SSL服务程序技术架构设计文档.md` ### 70.3 验证状态 - [x] 证书生命周期专项测试已通过,等待全量后端测试复审。 - [x] 新目录格式、重复保存唯一性、旧当前目录清理和失败回滚已覆盖自动化测试。 - [x] 前端历史版本面板和恢复操作已移除,等待前端构建复审。 - [!] 旧安装目录中的历史文件未执行批量清理,避免未经授权删除用户证书、私钥或备份;后续迁移清理需单独授权。 ## 七十一、登录界面用户化(2026-08-30) ### 71.1 本轮需求清单 - [✓] 登录页面标题由“管理员登录”调整为“用户登录”。 - [✓] 登录页面说明、密码占位符和无障碍标签统一使用“用户”文案。 - [✓] 登录流程阶段标题同步调整为“用户登录”,不改变服务端认证、角色识别和会话逻辑。 ### 71.2 验证状态 - [✓] 登录相关前端文件已完成修改,等待本轮构建复审。 - [!] 后端仍根据服务端返回结果识别超级管理员、管理员和普通用户,未因页面文案调整而改变权限模型。 ## 七十二、自动续期策略与任务并发保护(2026-08-30) ### 72.1 本轮实现内容 - [✓] 增加自动续期检查间隔、临近到期阈值、自动续期阈值、紧急阈值、最大重试次数和重试间隔配置。 - [✓] 设置接口支持读取和更新全部续期策略字段,并在配置非法时拒绝保存。 - [✓] 自动续期调度器根据证书剩余有效期动态调整检查频率。 - [✓] 紧急续期失败时按配置执行可取消的重试等待。 - [✓] 同一进程内证书申请任务创建增加临界区,避免并发请求重复通过活跃任务检查。 ### 72.2 验证状态 - [✓] 设置接口续期策略读写、非法阈值关系和敏感配置保护测试已通过。 - [✓] 后端 `go test ./...`、`go test -race ./...`、`go vet ./...` 和 `go mod verify` 已通过。 - [✓] 前端 `npm.cmd run build` 已通过。 - [!] 尚未进行真实 ACME、DNS 服务商、远程 SSH、生产 HTTPS 和多进程并发验收;这些仍需授权后的实机测试。 ## 七十三、服务重启任务恢复(2026-08-30) ### 73.1 本轮需求清单 - `[✓]` 服务启动时自动扫描数据库中仍处于排队或执行状态的任务。 - `[✓]` 将服务重启前未完成的任务标记为失败,并记录“服务重启恢复”执行阶段。 - `[✓]` 同步关闭未完成任务尝试,写入统一的中断说明和完成时间。 - `[✓]` 已完成和已取消任务不受启动恢复逻辑影响。 - `[✓]` 管理后台为“服务重启恢复”阶段补充中文显示名称。 ### 73.2 验证状态 - `[✓]` SQLite 任务仓储专项测试通过,覆盖排队任务、执行任务、执行尝试和已完成任务保护。 - `[✓]` 应用重启集成测试通过,覆盖首次启动写入未完成任务、关闭应用、重新启动和已完成任务保护。 - `[✓]` 后端 `go test ./...`、`go test -race ./...`、`go vet ./...` 和 `go mod verify` 已通过。 - `[✓]` 前端与桌面端前端构建、桌面端 Go 测试已通过。 - `[!]` 多进程同时启动时的跨进程任务调度仍不是本轮实现范围;服务重启恢复只负责清理持久化的未完成状态。 ## 七十四、Web 管理页面开关与系统设置完善(2026-08-30) ### 74.1 本轮需求清单 - `[✓]` 系统设置页在服务监听区域提供“开启 Web 管理页面”开关。 - `[✓]` 保留管理页面域名和公网 IP 配置,并明确关闭 Web 页面不影响桌面端本地管理。 - `[✓]` 修改 Web 页面开关后,设置接口返回需要重启 Scert 服务的提示。 - `[✓]` 设置接口保存 Web 页面开关状态,并在响应中返回脱敏后的配置视图。 ### 74.2 验证状态 - `[✓]` 后端设置接口定向测试通过,覆盖 Web 页面开关关闭、配置文件保存和重启提示。 - `[✓]` 网页端 `npm.cmd run build` 通过。 - `[✓]` 桌面端前端构建通过并同步资源引用。 - `[!]` 真实远程服务、Nginx 反向代理、生产 HTTPS 和浏览器视觉验收仍需在用户授权的目标环境执行。 ## 七十五、续期调度生命周期与环境变量完善(2026-08-30) ### 75.1 本轮需求清单 - `[✓]` 续期调度器使用内部可取消上下文,支持显式停止并等待后台检查退出。 - `[✓]` `App.Close()` 关闭应用时先停止续期调度器,再关闭 HTTP、数据库和日志资源。 - `[✓]` 重复启动、重复停止和停止后更新策略的行为保持幂等且不会重新执行已停止的调度器。 - `[✓]` 增加 `SCERT_WEB_ENABLED=true/false` 环境变量覆盖,仅影响当前进程,不回写配置文件。 - `[✓]` 非法 Web 开关环境变量会被拒绝,并返回中文配置错误。 ### 75.2 验证状态 - `[✓]` 续期调度器专项测试通过,覆盖停止、重复停止、策略唤醒和重试取消。 - `[✓]` 后端 `go test ./...`、`go test -race ./...`、`go vet ./...` 和 `go mod verify` 已通过。 - `[✓]` 网页端和桌面端前端 `npm.cmd run build` 已通过。 - `[✓]` 桌面端 Go `go test ./...` 和 `go vet ./...` 已通过。 - `[!]` 真实 ACME、DNS 服务商、远程 SSH、Nginx 反向代理和生产 HTTPS 验收仍需授权后的目标环境测试。 ## 七十六、桌面核心服务环境配置一致性(2026-08-30) ### 76.1 本轮需求清单 - `[✓]` 桌面/Wails 核心服务入口统一使用 `LoadWithEnv()` 读取受控环境变量。 - `[✓]` 配置文件不存在时,默认配置同样应用环境变量并执行完整校验。 - `[✓]` 桌面核心服务支持通过 `SCERT_WEB_ENABLED=false` 关闭 Web 静态页面。 - `[✓]` 桌面核心服务拒绝非法环境变量值,避免带错误配置启动。 ### 76.2 验证状态 - `[✓]` `backend/service` 环境配置专项测试通过。 - `[!]` 真实 Wails 桌面打包、Windows Service 和 Linux systemd 实机验收仍需在授权目标环境执行。 ## 七十七、登录账号自助修改密码(2026-08-30) ### 77.1 本轮需求清单 - `[✓]` 增加已登录账号修改自身密码的 API,接口受登录状态和同源请求保护。 - `[✓]` 修改密码前校验当前密码、两次新密码一致性和 8 到 12 个字符的密码策略。 - `[✓]` 支持配置中的超级管理员密码持久化到配置文件,并同步数据库中的主超级管理员摘要。 - `[✓]` 支持数据库用户修改自身密码,并在保存后使该用户的旧会话全部失效。 - `[✓]` 修改成功后清除当前会话 Cookie,要求使用新密码重新登录,避免继续使用旧会话。 - `[✓]` Web 管理页面增加“修改密码”弹窗入口,成功后自动返回登录页面。 ### 77.2 接口与验证状态 - `[✓]` 新增 `POST /api/v1/auth/password`,请求字段为 `current_password`、`new_password` 和 `confirm_password`。 - `[✓]` 后端专项测试覆盖超级管理员、数据库用户、旧会话失效、错误输入和新密码登录。 - `[✓]` 后端 `go test ./...` 和网页端 `npm.cmd run build` 已通过。 - `[!]` 真实部署环境的浏览器视觉复核、Wails 打包产物和远程 HTTPS 入口仍需目标环境验收。 ## 七十八、证书工作流错误信息脱敏(2026-08-30) ### 78.1 本轮需求清单 - `[✓]` 证书列表读取当前证书失败时,仅返回统一中文提示,详细错误写入服务日志。 - `[✓]` 证书部署和证书导入失败时,不再向浏览器返回底层路径、命令或凭据错误。 - `[✓]` 证书历史版本恢复失败时,审计日志只记录稳定的失败摘要,详细错误写入服务日志。 - `[✓]` 手动续期失败时返回稳定的中文错误摘要,避免把底层错误直接暴露给管理页面。 - `[✓]` 增加列表、导入、部署和历史版本恢复接口的错误脱敏回归测试。 ### 78.2 验证状态 - `[✓]` 证书接口专项测试通过。 - `[✓]` 后端 `go test ./...`、`go vet ./...` 和 `go mod verify` 已通过。 - `[✓]` 前端生产构建已通过。 - `[!]` 真实 ACME、DNS Provider、SSH 部署、Nginx 反向代理和生产 HTTPS 仍需在授权目标环境执行实机验收。 ## 七十九、证书任务与部署报告错误信息脱敏(2026-08-30) ### 79.1 本轮需求清单 - `[✓]` 证书任务失败时不再把 ACME、SSH、远程路径或命令执行错误写入任务消息和 HTTP 响应。 - `[✓]` 证书任务底层错误保留在服务日志中,便于管理员通过日志排查具体原因。 - `[✓]` 任务接口返回的失败部署结果统一使用“证书部署失败”摘要。 - `[✓]` 无任务仓储的直接证书申请接口同样对部署报告失败项进行脱敏。 - `[✓]` 增加任务失败错误脱敏和直接申请部署报告脱敏回归测试。 ### 79.2 代码与验证状态 - `[✓]` 新增 HTTP API 层错误摘要和部署报告脱敏辅助逻辑。 - `[✓]` `go test ./internal/httpapi` 定向测试通过。 - `[✓]` 后端 `go test ./...`、`go test -race ./...`、`go vet ./...`、`go mod verify` 和 `git diff --check` 已通过。 - `[~]` 本批源码提交和远程推送待完成。 - `[!]` 真实 ACME、DNS Provider、SSH 部署、Nginx 反向代理和生产 HTTPS 仍需在授权目标环境执行实机验收。 ## 八十、证书部署接口报告脱敏与本轮复核(2026-08-30) ### 80.1 本轮需求清单 - `[✓]` 直接证书部署接口统一调用部署报告脱敏逻辑。 - `[✓]` 证书文件导入接口统一调用部署报告脱敏逻辑。 - `[✓]` 失败报告仅保留服务器编号、服务器名称、汇总数量和状态,不返回远程证书路径、私钥路径、命令输出或权限错误。 - `[✓]` 增加直接部署接口和证书导入接口的内部错误脱敏回归测试。 - `[✓]` 保留日志中的底层错误,便于管理员排查真实部署失败原因。 ### 80.2 本轮验证状态 - `[✓]` `go test ./internal/httpapi` - `[✓]` `go test ./...` - `[✓]` `go test -race ./...` - `[✓]` `go vet ./...` - `[✓]` `go mod verify` - `[✓]` `npm.cmd run build` - `[✓]` `git diff --check` - `[✓]` 本轮源码提交已推送,且本地 `main` 与远程 `Scert/main` 哈希一致。 ### 80.3 验收边界 - `[!]` 真实 DNS 服务商、Let’s Encrypt Production、远程 SSH 证书部署、Nginx 反向代理、生产 HTTPS、Windows Service、Linux systemd、Wails 打包、Windows ACL 和 MySQL 实例仍需在授权目标环境执行实机验收。 - `[!]` 工作区中已有的 `desktop/frontend/dist/index.html`、`dist/` 和 `backend/.patch*` 未删除、未纳入本轮提交,等待用户单独授权清理。 ## 八十二、证书部署路径与任务启动状态一致性(2026-08-31) ### 82.1 本轮需求清单 - `[✓]` 服务器证书、完整证书链和私钥路径必须使用绝对路径,避免相对路径写入未知远程目录。 - `[✓]` 拒绝证书、完整证书链和私钥配置为同一路径,避免部署时发生静默覆盖。 - `[✓]` 服务器配置解析层和实际部署层均执行路径校验,避免绕过单层校验。 - `[✓]` 证书任务在创建尝试成功但切换到“执行中”状态失败时,自动收敛为失败状态。 - `[✓]` 任务启动失败时同步结束任务尝试并记录错误审计,避免数据库残留执行中任务。 ### 82.2 代码与验证状态 - `[✓]` 更新 `backend/internal/deployment/model.go` 和 `service.go`,增加绝对路径与重复路径校验。 - `[✓]` 更新 `backend/internal/httpapi/task_api.go`,补充任务启动状态写入失败的清理和审计逻辑。 - `[✓]` 增加部署路径和任务启动失败回归测试。 - `[✓]` 后端 `go test ./...` 通过。 - `[✓]` 后端 `go test -race ./...` 通过。 - `[✓]` 后端 `go vet ./...` 通过。 - `[✓]` 后端 `go mod verify` 通过。 - `[~]` 网页端、桌面端前端和桌面端 Go 全量验证待本轮后续命令完成。 - `[✓]` 本轮源码提交和远程推送已完成,本地 `main` 与远程 `Scert/main` 哈希一致。 ### 82.3 验收边界 - `[!]` 真实 DNS 服务商、Let’s Encrypt、SSH 主机、Nginx/Caddy/Apache、生产 HTTPS、Windows Service、Linux systemd、Wails 打包、Windows ACL、MySQL 和真实防火墙链路仍需在授权目标环境验收。 - `[!]` 工作区已有的 `desktop/frontend/dist/index.html`、`dist/`、`backend/.patch*` 和构建产生的 `.exe` 未删除、未纳入本轮源码提交。 ## 八十一、DNS 在线测试传播参数接入与全量复核(2026-08-30) ### 81.1 本轮需求清单 - `[✓]` DNS 测试器支持使用配置中的 DNS 传播等待时间,不再固定使用 30 秒。 - `[✓]` DNS 测试器支持使用配置中的 DNS 轮询检测间隔,不再固定使用 2 秒。 - `[✓]` Web 初始化 DNS 在线测试的请求上下文超时与传播等待配置同步,并保留清理记录所需的缓冲时间。 - `[✓]` CLI 初始化 DNS 在线测试使用与配置一致的传播等待参数和请求超时。 - `[✓]` 保留无效配置和旧构造函数的安全默认值,避免已有调用方失去超时保护。 - `[✓]` 增加 DNS 测试器配置生效和 Web 请求截止时间的回归测试。 ### 81.2 代码与验证状态 - `[✓]` 更新 `backend/internal/dnsprovider/tester.go`,增加可配置传播等待时间和轮询间隔的构造函数。 - `[✓]` 更新 `backend/internal/app/app.go`,应用启动时注入 ACME DNS 传播配置。 - `[✓]` 更新 `backend/internal/cli/root.go`,CLI 初始化流程注入 DNS 传播配置并计算请求超时。 - `[✓]` 更新 `backend/internal/httpapi/setup.go`,Web DNS 在线测试按配置计算请求上下文超时。 - `[✓]` 增加 DNS 测试器和 Web API 超时专项回归测试。 - `[✓]` `go test ./...` - `[✓]` `go test -race ./...` - `[✓]` `go vet ./...` - `[✓]` `go mod verify` - `[✓]` `go build ./cmd/scert` - `[✓]` `go build ./cmd/scert-admin` - `[✓]` 网页端 `npm.cmd run build` - `[✓]` 桌面端前端 `npm.cmd run build` - `[✓]` `git diff --check` ### 81.3 验收边界 - `[!]` 尚未使用新的真实 DNS 服务商凭据执行公网 TXT 创建、传播和清理验收。 - `[!]` Let’s Encrypt Production、真实 SSH 主机、公钥安装、证书部署、Nginx 反向代理和生产 HTTPS 仍需在用户授权的目标环境执行实机验收。 - `[!]` Windows Service、Linux systemd、Wails 桌面打包、Windows ACL、MySQL 实例和真实防火墙链路仍需目标环境验收。 - `[!]` 工作区中已有的 `desktop/frontend/dist/index.html`、`dist/` 和 `backend/.patch*` 未删除、未纳入本轮提交,等待用户单独授权清理。 ## 八十三、Linux systemd 服务注册补全与全量代码复审(2026-08-31) ### 83.1 本轮需求清单 - `[✓]` Linux 执行 `scert service install` 时自动生成对应的 systemd unit 文件。 - `[✓]` unit 文件使用绝对程序路径、配置路径和工作目录,避免服务启动时依赖当前终端目录。 - `[✓]` 服务注册前执行 `systemctl daemon-reload`,再执行 `systemctl enable`。 - `[✓]` 服务卸载时先取消开机启动,再移除对应 unit 文件并重新加载 systemd。 - `[✓]` 服务名称经过路径穿越校验,禁止将 unit 文件写入 `/etc/systemd/system` 之外的位置。 - `[✓]` 增加 Linux unit 渲染和服务名称安全校验回归测试。 ### 83.2 代码与验证状态 - `[✓]` 更新 `backend/internal/servicehost/linux.go`,补全 unit 文件生成、安装、卸载和 systemd 重载流程。 - `[✓]` 新增 `backend/internal/servicehost/linux_test.go`,覆盖 unit 内容、配置路径、工作目录和路径穿越防护。 - `[✓]` 后端 `go test ./...` 通过。 - `[✓]` 桌面端 Go `go test ./...` 通过。 - `[✓]` 网页端 `npm.cmd run build` 通过。 - `[✓]` 桌面端前端 `npm.cmd run build` 通过。 - `[✓]` 后端 race、vet、依赖校验、构建和最终差异检查通过。 - `[✓]` 本轮 Linux systemd 源码和测试已提交并推送。 ### 83.3 验收边界 - `[!]` Linux systemd unit 的实际安装、启停、开机启动和权限效果仍需在授权 Ubuntu 主机上验收。 - `[!]` 真实 DNS 服务商、Let’s Encrypt Production、远程 SSH 部署、Nginx 反向代理、生产 HTTPS、Windows Service、Wails 打包、Windows ACL、MySQL 和真实防火墙链路仍需目标环境验收。 - `[!]` 工作区已有的 `desktop/frontend/dist/index.html`、`dist/`、`backend/.patch*` 和构建产生的 `.exe` 未删除、未纳入本轮源码提交。 ## 八十四、系统服务名称路径安全复审与全量验证(2026-08-31) ### 84.1 本轮需求清单 - `[✓]` Linux、Windows 的服务名称校验统一拒绝空白名称、`.`、`..` 以及正反斜杠路径分隔符。 - `[✓]` Linux unit 文件路径生成不会接受 `../`、`a/b` 或 `a\\b` 等路径穿越输入。 - `[✓]` Windows 卸载入口与安装、启动、停止入口使用同一套服务名称校验。 - `[✓]` 新增跨平台服务名称安全回归测试,并保留 Linux unit 渲染测试。 ### 84.2 验证状态 - `[✓]` 后端 `go test -count=1 ./...` 通过。 - `[✓]` 后端 `go test -race -count=1 ./...` 通过。 - `[✓]` 后端 `go vet ./...`、`go mod verify`、`go build ./cmd/scert` 和 `go build ./cmd/scert-admin` 通过。 - `[✓]` Linux amd64 与 Windows amd64 servicehost 测试二进制编译通过。 - `[✓]` 桌面端 Go 测试、网页端生产构建和桌面端前端生产构建通过。 - `[✓]` 本轮服务名称校验源码和测试已提交并推送。 ### 84.3 验收边界 - `[!]` 当前验证在 Windows 开发机完成;Linux servicehost 测试仅完成 amd64 交叉编译,systemd 实际安装、启停、开机启动和权限效果仍需授权 Ubuntu 主机实机验收。 - `[!]` 真实 DNS、ACME Production、SSH/SFTP 证书部署、Nginx 反向代理、生产 HTTPS、Windows Service、Wails 安装包、Windows ACL、MySQL 实例和真实防火墙链路仍不属于本地自动化测试结论。 - `[!]` 工作区中既有的 `desktop/desktop.exe`、`desktop/frontend/dist/index.html`、`dist/`、`backend/.patch*` 和 `backend/*.exe` 未删除、未纳入本轮提交。 ## 八十五、动态系统服务安装安全增强与全量复审(2026-08-31) ### 85.1 本轮需求清单 - `[✓]` 动态 Linux systemd unit 增加配置文件存在条件、系统目录只读保护和网络地址族限制。 - `[✓]` CLI 支持可选运行用户、用户组和服务可写绝对路径配置。 - `[✓]` 服务名称、服务文本、路径和账户标识增加控制字符及危险格式校验。 - `[✓]` Linux、Windows 服务启停和卸载入口统一规范化服务名称,避免首尾空格造成操作对象不一致。 - `[✓]` 增加动态 unit 安全策略、相对可写路径和配置注入防护回归测试。 ### 85.2 验证状态 - `[✓]` 后端 `go test -count=1 ./...` 通过。 - `[✓]` 后端 `go test -race -count=1 ./...` 通过。 - `[✓]` 后端 `go vet ./...`、`go mod verify`、CLI 构建通过。 - `[✓]` Linux amd64 和 Windows amd64 servicehost 测试编译通过。 - `[✓]` 桌面端 Go 测试、网页端生产构建、桌面端前端生产构建通过。 - `[✓]` Wails `v2.11.0` Windows amd64 生产构建通过。 - `[✓]` Windows 安装脚本 PowerShell 语法解析通过;当前开发机未安装 Bash,因此 Linux shell 语法检查未执行。 ### 85.3 交付边界 - `[!]` Linux systemd 实际安装、启停、开机启动和权限效果仍需在授权 Ubuntu 主机实机验收。 - `[!]` Windows Service 实际安装、ACL、开机启动和升级仍需在授权 Windows 主机实机验收。 - `[!]` 真实 DNS 服务商、Let’s Encrypt Production、远程 SSH 部署、Nginx 反向代理、生产 HTTPS、MySQL 和真实防火墙链路仍需目标环境验收。 ## 八十六、动态 systemd 加固与 DNS 测试环境隔离复核(2026-08-31) ### 86.1 本轮需求清单 - `[✓]` 动态 Linux systemd unit 与固定部署 unit 使用一致的最小权限和系统目录保护策略。 - `[✓]` 动态 unit 增加能力集、设备、内核、命名空间、实时性、SUID 和系统调用架构限制。 - `[✓]` DNS Provider 单元测试显式关闭 CNAME 跟随,避免测试环境 DNS 不可用时进入外部网络等待。 - `[✓]` 保留生产环境默认 CNAME 委派行为,不通过测试配置改变运行时默认策略。 ### 86.2 验证状态 - `[✓]` `go test -p 1 -count=1 -timeout=3m ./...` - `[✓]` `go test -race -p 1 -count=1 -timeout=5m ./...` - `[✓]` `go vet -p=1 ./...` - `[✓]` `go mod verify` - `[✓]` Linux amd64 `servicehost` 测试二进制交叉编译。 - `[✓]` 网页端 `npm.cmd run build`。 - `[✓]` 桌面端 Go `go test -p 1 -count=1 ./...`。 - `[✓]` `git diff --check`。 - `[~]` 本轮源码提交和远程推送待完成。 ### 86.3 复审边界 - `[!]` Linux systemd unit 的实际安装、启停、开机启动和沙箱权限效果仍需授权 Ubuntu 主机实机验收。 - `[!]` 当前未运行会覆盖用户保留桌面构建产物的桌面前端生产构建。 - `[!]` 真实 DNS 服务商、Let’s Encrypt Production、远程 SSH 部署、Nginx 反向代理、生产 HTTPS、Windows Service、Windows ACL、MySQL 和真实防火墙链路仍需目标环境验收。 - `[!]` 工作区已有的 `desktop/desktop.exe`、`desktop/frontend/dist/index.html`、`dist/`、`backend/.patch*` 和 `backend/*.exe` 未删除、未纳入本轮源码提交。 - `[!]` 工作区已有的 `desktop/desktop.exe`、`desktop/frontend/dist/index.html`、`dist/`、`backend/.patch*` 和 `backend/*.exe` 未删除、未纳入源码提交。 ## 八十七、请求安全、DNS 状态与认证稳定性审查(2026-09-15) 详细记录和证据范围见 `全面审查测试与优化记录.md`,本节不覆盖旧轮的实机验收结论。 - `[✓]` 恢复任务与工作区,分清管理部署机和推送目标机;保留禁止修改 `pcux.cn` 的边界。 - `[✓]` 桌面模块同步 SSH 安全依赖,恢复只读模块测试。 - `[✓]` 登录、退出和首次初始化增加跨源写入防护。 - `[✓]` 长操作采用有限上下文与独立响应期限,真实套接字回归通过。 - `[✓]` 初始化改用专用互斥锁,签发不再阻塞配置读取,并发初始化拒绝。 - `[✓]` DNS 验证结果与当前输入、请求代次和有效期绑定,防止旧响应覆盖。 - `[✓]` 嵌套续期、云 API 报告脱敏,保留清理失败等重要状态。 - `[✓]` 认证状态过期回收、容量上限、固定长度限流键和并发退出回归。 - `[✓]` 新初始化默认阿里云;兼容已保存服务商,不建议通配全部权限。 - `[✓]` 后端全量测试、竞态检测、静态检查、模块校验、漏洞复扫;最终覆盖率 64.0%。 - `[✓]` 前端 12 项自动化测试、生产构建、全依赖审计;桌面模块最终测试通过。 - `[✓]` Linux 和 Windows 安装脚本语法检查,未执行安装器。 - `[✓]` 最新源码 `667f769` 已推送,远程 HEAD 一致;独立干净副本依赖安装及前端 12 项测试通过。 - `[!]` PowerShell 策略拒绝发布脚本,未生成最新 Linux 候选,未绕过策略;旧候选不包含本轮修复。 - `[!]` 本地服务启动被执行策略拒绝,本轮实际浏览器验收未执行,未尝试绕过。 - `[!]` 写权限探测逐级尝试父托管区的边界需专项整改;只读精准检查不等于写路径安全完成。 - `[!]` 真实初始化、正式 ACME、HTTPS/SNI、业务推送、升级回退及目标平台验收仍未完成。