Skip to content

release: v0.3.9 正式版 - #8

Merged
zhuxbo merged 23 commits into
mainfrom
dev
Jul 20, 2026
Merged

zhuxbo merged 23 commits into
mainfrom
dev

Conversation

@zhuxbo

@zhuxbo zhuxbo commented Jul 20, 2026

Copy link
Copy Markdown
Owner

发布 0.3.9 正式版。

  • 已完成本地 finish-check
  • 已完成宝塔 nginx/Apache Docker 集成验证
  • 合并后按正式发布事务构建、暂存、发布并对账

zhuxbo added 23 commits July 12, 2026 15:35
- 结果判定改白名单:仅「dict 且 status is True」视为成功,非 dict、缺 status 键、非 bool 真值等异常形态一律判失败(原黑名单仅拦 status is False,失败被误报成功并回调 success)
- 新增 _verify_web_service:SetSSL 成功后经 public.checkWebConfig() 校验配置、serviceReload() 幂等重载并识别 stderr 错误特征,reload 失败视为部署失败(phase='reload')
- 失败回调 failure:deploy_multi 聚合各站点失败原因,单站点 deploy 失败路径补发 failure 回调(此前失败无任何回调)
- api_client.callback 新增可选 message 字段携带失败原因,超长按服务端上限 500 字符截断,空值不上送保持兼容
- mock_bt/public.py 补 checkWebConfig/serviceReload 桩,新增 17 项测试覆盖白名单判定、reload 判定与失败回调
- docker-compose 补 container_name 对齐测试脚本寻址;集成环境其余既有失效另行登记
- 同步 CLAUDE.md 规范对齐要点与 skills/sslbt-dev.md 部署流程说明
- entrypoint 重写:复用官方镜像 /www.tar.gz 离线还原面板与 Web 服务,不再依赖被顶掉的 /bt.sh 或面板 Web 进程
- 经 panelSite.AddSite 把测试站点注册进面板库,SetSSL 可命中站点;pyenv 调用并以库表反查校验
- 新增 forward.py loopback 转发(127.0.0.1:18080 → mock-api),满足 API 客户端「非 loopback 强制 HTTPS」与 SSRF 拦截约束
- call_plugin 改用面板 pyenv 执行并重定向面板杂项输出,异常统一转 JSON,不再触发 set -e 中断整个套件
- 修复 ${params:-{}} 花括号截断导致的 Python 语法错误;compose 环境变量改为 MOCK_API_HOST/PORT
- 脚本对齐当前插件 API:add_cert 补 api_url/api_token/site_names,替换已废弃的 test_connection/get_dashboard 断言
- 新增失败路径用例:部署到不存在站点须判失败且回调 failure,端到端覆盖 SetSSL 白名单判定与 _verify_web_service 真实 reload 校验
- 计数改文件累加(旧子 shell 计数恒为 0),存在失败时 make docker-test 退出非零
- 同步 skills/sslbt-dev.md 集成测试环境说明
- setup() 原样丢弃 AddCrontab 返回值并无条件报成功,创建失败时自动续签定时任务实际不存在而用户无感知
- 改为双重校验:显式 status is False 直接判失败并透传面板错误;其余形态以 _find_cron_ids() 入库反查为准
- 入库反查容忍宝塔版本返回形态漂移(事实创建成功不误报失败),未入库的谎报成功与异常形态一律判失败
- setup_cron 端点已有 status/message 透传,前端自动获得真实失败提示
- 改写 test_setup_success 为「成功形态 + 真实入库」契约,新增 5 项失败形态与优先级测试
- 同步 CLAUDE.md 规范对齐要点与 skills/sslbt-dev.md 模块说明
- needs_renewal 对空/不可解析 cert_expires_at 改判为未知需处理进入 API 查询回填;processing 证书无论到期是否已知都跟进签发;已明确过期仍停止等人工(spec §3.2/§3.5)
- deployer 证书解析或 metadata 写入失败不再仅告警后回调 success,改为回调 failure 带原因并抛 DeployError,本地状态未落盘时促使下轮 cron 重试
- 手动 deploy_cert 补中间证书守卫(空 CA 拒绝部署避免残链覆盖),文案与 renew 自动路径一致
- deploy_cert/deploy_all 获取续签互斥锁(data/renew.lock,非阻塞、进程内可重入),避免与 cron 并发交错执行 SetSSL/reload
- SetSSL 写入前 pre-flight 校验既有 Web 配置(损坏则 phase=preflight 快速失败),并经 GetSSL 捕获原证书用于回滚
- 写入后 checkWebConfig+serviceReload 失败时回滚原证书并重载,回滚成功/无原证书/回滚仍失败均在错误与回调 message 如实反映
- 覆盖续签判定空值/processing、deployer metadata 失败、CA 守卫、续签锁 busy、pre-flight 拒绝与回滚回归测试,同步部署流程文档
- 一键部署列表对部分匹配站点默认不勾选,并列出未被证书覆盖的域名,避免误将未覆盖域名的站点纳入部署
- 编辑证书站点绑定弹窗同样显示未覆盖域名,界面保持一致(匹配仍由后端 match_sites_for_cert/match_domains 提供)
- cron 注册改用 sys.executable(面板 pyenv)而非裸 python3,取不到时回退 python3,避免环境不一致致续签整体不可运行
- 续签结束原子写 data/renew_status.json(时间戳/成功/等待/失败计数,0600),新增 get_renew_status,index.html 展示"最近续签"
- 补 unmatched 字段、cron 解释器、续签状态文件与 get_renew_status 回归测试,同步 skills 文档
- SensitiveFilter 改为对 args 格式化后的完整消息脱敏,覆盖 dict/list 参数(此前仅过滤 str 参数)
- _FILTERS 增补单引号 dict 形态与 api_token 等复合词,并扩展 key=value 复合词匹配
- fetch_deploy_url 改走统一 APIClient(HTTPS 强制 + SSRF + DNS Rebinding + token 校验),拒绝 http scheme
- 移除裸 urlopen 与手动 check_ssrf,避免绕过项目统一安全出口
- 补 dict/私钥参数脱敏与 http 拒绝回归测试,重写 fetch 测试为 mock 统一客户端
- SiteManager.get_sites 查询失败(DB 缺失/锁定/表结构漂移)抛 SiteQueryError,与"确认零站点"严格区分
- deploy_multi 一次查询站点清单复用检测,不再逐站点全库扫描放大锁窗口
- 清单查询失败或为空(迁移/重装等异常中间态)时放弃本轮删除判定,保守视为全部存在,绝不解绑
- 仅当清单查询成功且非空时,才将不在清单中的绑定站点解除并持久化,其余站点继续部署
- 首次检测续签结果与部署回调统一记 failure 带"站点已删除",解绑后不再重复失败
- file_verifier 适配站点清单查询失败(安全跳过放置);UI 查询路径失败如实报错
- 回归测试覆盖缺失 DB/漂移表结构、锁定语义与空清单场景,均不解绑
- fetch_deploy_url/APIClient._build_api_url 保留部署链接 path,修复反代子路径(如 /manager/api/deploy)被改写回 host-root 致 404;session/config 持久化的 api_url 同步携带子路径
- _capture_current_ssl 在 GetSSL 拿不到有效证书时回退读宝塔证书目录 fullchain.pem/privkey.pem,与 site_manager 的 vhost/cert、vhost/ssl 约定一致
- tests/ 目录 flake8 归零(移除未使用 import、拆分超长行、修正未使用局部变量),与 src/ 同标准
- 补反代子路径/标准链接、GetSSL 优先/文件回退/双源均无回归测试
- finish-check 新增「检查范围」(工作区/工作分支模式,分支模式含逐提交格式检查),lint 检查扩展到 tests/ 零告警
- finish-check 补宝塔 API 站点清单查询失败与零站点严格区分、续签回调语义/metadata 失败不回调 success/到期未知需处理/HTTP 出口统一走 APIClient
- deploy-spec §5.3 私钥来源补 pending-keys 待确认私钥一档(配对校验通过才用,部署成功后转正)
- deploy-spec §10.3 私钥保护改为"配对校验通过且部署成功后",消除与 §3.8 的内部矛盾,与四仓副本保持一致
- local 模式到期时间未知且无在途 CSR 时,先 query_order 回填 cert_expires_at/serial,再按 needs_renewal 判定,不再盲目提交 CSR
- 回填后远期本轮不续签,临期/已到期才走重签,与 pull 模式及姊妹仓 sslctl 语义对齐
- 查询失败向上抛出按失败处理;服务端无证书内容或证书解析失败则本轮跳过,待下轮重试
- 订正 needs_renewal 注释:其仅做前置放行判定,实际查询回填由各模式处理器完成
- 新增 TestLocalUnknownExpiryRefill 覆盖查询计数、远期不提交、临期提交、查询/解析失败不提交
- _handle_processing 与 _submit_new_csr 立即 active 分支:将 _cleanup_pending_key 移到 _check_deploy_results 之后
- 全部站点部署失败时 _check_deploy_results 抛错,cleanup 不再执行,pending 私钥保留供下轮重试,符合 spec §3.8
- 部分成功/全部成功仍照常清理(私钥已被消费),行为不变
- 崩溃恢复、验证方式不兼容、submit APIError 三处 cleanup 语义正确,保持不动
- 新增 TestDeployFailureRetainsPendingKey 覆盖全失败保留、成功清理、部分成功清理、立即 active 全失败保留
- _set_ssl 捕获 SetSSL 抛异常/返回非成功状态两种失败:写入前已捕获的 prev 证书经 _rollback_after_setssl_failure 尝试回滚,消除"写坏证书后直接失败"残留
- 回滚为 best-effort:prev 为空时 no-op,回滚自身异常仅记日志,不掩盖 SetSSL 原始错误
- _write_renew_status 改用 tempfile.mkstemp 随机名(O_EXCL 创建不跟随符号链接)+ 原子替换,消除固定名 .tmp 被预置符号链接经 O_TRUNC 覆盖任意文件的风险,写失败清理临时文件
- 新增测试覆盖 SetSSL 写后返回 False 回滚、SetSSL 抛异常回滚、无 prev 保留原始错误、预置符号链接不覆盖 victim
- 有意行为变更:绑定站点在面板清单缺失时首轮仅记 site_missing(按 failure 上报不解绑),连续两轮确认(阈值 SITE_MISSING_CONFIRM_THRESHOLD=2、间隔 ≥12h、计数持久化 metadata.site_missing_counts)后才解绑,缩小迁移/重装中途不完整快照误清绑定半径;存活/恢复站点计数清零
- pending 私钥清理判据从"是否抛错"改为"是否已被消费":deploy_multi 任一站点成功即先清理再执行 _check_deploy_results 照常抛错上报,堵住"部分成功+站点缺失/删除"轮次 metadata 已落盘但私钥泄漏(承接前一提交全失败保留 pending 的后续收口)
- 行为变更:processing 证书无绑定站点可部署时不再静默跳过,改为清 pending 私钥、清空签发状态、发 failure 回调并按失败上报,消除"每日空查询+私钥永驻"孤儿;重新绑定后走正常重签
- 缺失间隔门控与损坏时间戳兜底:距上次计入不足 12h 的再次缺失不递增(保持疑似态与失败上报);naive(无时区)时间戳按损坏处理修复为当前时间且本轮不递增,消除 aware-naive 相减中止整个 deploy_multi
- 移除无生产调用的单站点 Deployer.deploy,统一走 deploy_multi,避免重复维护校验/回调/metadata(三处守卫覆盖迁移到 deploy_multi 变体测试)
- 续签提前天数上限统一 MAX_RENEW_BEFORE_DAYS=30,超限拒绝并保留本地配置,deploy-spec §2.9 同步
- renew._check_deploy_results 对 site_missing 同样抛错按 failure 上报;固化旧单轮解绑行为的测试改走两轮确认,新增缺失计数/两轮解绑/恢复清零/跨 12h/孤儿收敛/naive 时间戳等回归
- 回调 message 仅在 status=failure 时填充,success 不带(api_client.callback 以 status 门控)
- message 复用 logger 脱敏规则过滤 Bearer/Basic/私钥/token 后再截断,先脱敏后截断避免残留半个凭证
- 客户端截断上限收紧至 256 字符(服务端上限 500),CALLBACK_MESSAGE_MAX 同步调整
- deployer/renew 全部 failure 发送点均携带简明失败原因,success 路径 message 为空不带出
- 防御性核实:仅 deployer 与 renew._send_failure_callback 两处发送回调,status 恒为 success/failure,pending 仅存于本地 renew_status,绝不流向回调
- 文档同步:deploy-spec §2.8、skills、CLAUDE.md、finish-check 标注可选 message(仅 failure、脱敏、≤256)
- 测试:failure 携带并脱敏 Bearer、success 不带、超长截断至 256,并补脱敏先于截断的跨界用例(凭证跨 256 边界不泄漏半截)
- 新增 cert_utils.validate_site_name_component:拒绝空值、路径分隔符(/ 与 \)、.. 与绝对路径
- deployer._read_site_cert_files 读取宝塔证书目录前校验 site_name,并在打开前对 fullchain/privkey 做符号链接检查,避免构造站点名或预置软链读到目录外文件
- site_manager._check_ssl 探测证书路径前同样校验 site_name,非法名视为未启用不再探测目录外路径
- 仅加固实际用作路径的场景,file_verifier 等纯匹配/展示用途不动
- 测试:恶意 site_name(../x、/etc/passwd、a/b、..)被拒、符号链接目标被拒、正常域名不受影响
- CLAUDE.md 移除实现细节留文档指针,与三兄弟仓统一为精简概览;网络/升级安全细节并入 skills 新增「安全机制」章节(逐条对源码核实),内容零丢失
- 修正 skills 过时的"站点删除自愈"描述:单轮解绑改为两轮确认(阈值 2 + 间隔 ≥12h)
- finish-check 新增「deploy-spec.md 跨仓一致性」检查(触碰 spec 时用 md5/diff 校验四仓字节一致)
- finish-check 补 site_name 路径穿越、站点缺失两轮确认解绑、回调 message 先脱敏后截断检查;修正 Python 兼容性表述为 CI 3.9/3.12 两端 + 宝塔 pyenv
- README 续签提前天数改为服务端下发语义(默认 14、上限 30、超限保留本地配置),修正原"设置页配置、最大 13 天"双重过时表述,与 deploy-spec §2.9 及代码一致
- 对齐服务端 CSR 提交异步签发契约,移除立即 active 部署分支与冗余测试
- 单证书和批量部署存在失败时如实返回失败状态
- 解绑落盘失败时保留原绑定并通过回调及续签结果显式上报
- 更新共享规范并补齐部署与解绑故障回归测试
- 明确 dev 灵活测试版与 main 确定性正式版的发布边界
- 统一正式产物、标签、GitHub Release 和多节点恢复约束
- 规范 AGENTS、CLAUDE 与扁平 Skill 的单一来源和防漂移规则
- 建立精简智能体入口和扁平 Skill 路由,统一工具薄入口
- 引入确定性单资产构建、发布 manifest 与多节点事务恢复
- 增加发布 mock、防漂移检查和 CI 门禁
- 收紧安装包 SHA256 校验并更新维护文档
- 修复 Bash 3.2 构建参数兼容、dev installer 隔离及安装通道持久化
- 以候选封存、索引 CAS、唯一事务锁和 forward-only 恢复阻止并发覆盖与旧 bundle 重放
- 补齐多节点失败回滚、索引读取故障和中断恢复的 mock 回归测试
- 强化 Codex 路由、Skill 元数据、Make/CI 接线及 warning/skip 防漂移检查
- 新增 remote-release 与 finish-check 的仓库级 Codex 原生 Skill
- Claude 自定义命令收口为相同的两个薄入口,移除 build-release 命令
- 扩展防漂移检查并补齐工具入口集合回归测试
- 签发与部署计数分离,各自 >=10 触顶进入 CAPPED 静默;过期转 EXPIRED;触顶/过期/policy 阻断不发回调
- 自动续签回调收敛到编排层统一发送,deploy_multi 增加 send_callback,第 10 次失败标注已达重试上限
- CSR 提交前原子持久化 pending key/CSR 作为在途标记,transport 不确定结果下轮查询订单恢复,绝不重复 POST
- 查询状态归一 pending/approving 为 processing 继续等待;订单终态持久化后停止提交,状态未变不重复记 error/落盘
- 策略派生 derive_or_validate_renew_policy 唯一权威:SAN 含 IP 强制 local/file,新增 batch_set_renew_policy 前后端联动
- 配置加载计算型语义迁移:旧 pending 归一、旧计数触顶 CAPPED(legacy)、旧非法 IP 配置进入 policy_blocked
- deploy-spec 补全状态语义/回调契约/计数终止规则,移除 sslnas,点名四仓同步清单并完成同步
- 更新 sslbt-dev/finish-check skill 与测试,删除不可达的重提交死代码
- GNU stat 无 -f '%Lp',失败时仍向 stdout 输出文件系统信息,导致 Linux 上权限校验必然失败
- 新增 file_mode/sha256_stdin 统一走 python3,移除 stat/shasum 的 BSD 与 GNU 分支
- 测试 mock 的 sha256sum 同步改用 python3 hashlib,不再依赖 perl shasum
- Linux 容器(3.9/3.12 非 root)与 macOS 本地完整模拟 CI 门禁通过
@zhuxbo
zhuxbo merged commit 7e3518f into main Jul 20, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant