# BailingHub v0.1.8:首次管理员只创建一次 `v0.1.8` 修复无人值守安装与 demo 启动路径中的管理员生命周期问题:首次管理员现在只会在管理员表为空时创建。后续针对同一持久化数据库的服务重启、版本升级、容器重建或重新安装,都不会再次协调或覆盖已有账号。 ## 为什么要修 部署系统可以提供“首次安装时创建管理员”的能力,但不能把启动配置永久当成管理员账号的权威来源。 如果每次启动都根据环境变量重写账号,管理员主动改密后,服务重启可能把旧的 bootstrap 密码重新写回数据库。这既破坏运维预期,也会让旧部署配置持续拥有不应保留的密码重置能力。 `v0.1.8` 将这两种动作明确分开: - **bootstrap**:只负责空数据库的首次管理员创建; - **显式管理**:后续创建账号或重置密码继续使用 `npm run admin:create`。 ## 主要变化 ### Create-once bootstrap 使用成对环境变量: ```text BAILING_BOOTSTRAP_ADMIN_USERNAME BAILING_BOOTSTRAP_ADMIN_PASSWORD ``` 语义如下: - 两个变量都未配置:跳过自动创建; - 只配置其中一个:拒绝启动,避免半配置状态; - 管理员表为空:创建首个启用的 `admin` 账号; - 管理员表已有任何账号:不修改任何账号、密码、角色或启用状态。 ### 并发冷启动安全 MySQL 模式使用命名锁和事务串行化首次创建。多副本同时冷启动时,只有一个副本能够创建首个管理员;无法取得初始化锁时,服务会失败退出,而不是在不确定状态继续运行。 ### demo 与安装器采用同一契约 - 一键安装器生成随机首次管理员密码,并通过 bootstrap 环境变量传入; - demo seed 使用同一 create-once 逻辑; - 重启不会重置管理员密码; - 服务日志不再打印管理员密码。 ### 管理员仓储兼容修复 显式修改密码时,如果调用方没有提供角色: - 新账号使用 `admin` 作为插入缺省角色; - 已有账号保留原角色。 这避免了 MySQL 在执行重复键更新前,先因非空角色列缺值而拒绝请求。 ## 升级与兼容性 - 不需要数据库迁移; - 不改变 Client API、执行器协议、工具签名或 ACC 语义; - 既有 `npm run admin:create` 保持可用; - 保留数据库的升级、重装和容器重建不会重置账号; - 只有删除持久化数据库后的真正全新安装,才会重新创建首个管理员。 升级前仍应按常规流程备份数据库与部署配置。若历史部署继续保留 `BAILING_DEMO_ADMIN_PASSWORD`,它只服务于兼容的 demo 配置,不再构成每次启动重置管理员的依据。 ## 验证 发布前执行: ```bash npm run typecheck npm test npm run security:scan npm run release:check ``` 同时在真实 MySQL 上验证: 1. 空管理员表能够首次创建; 2. 管理员改密后重启,旧 bootstrap 密码不会恢复; 3. 多副本冷启动只创建一个首个管理员; 4. 日志不包含首次管理员密码; 5. Docker demo CI 在改密并重启后仍能使用新密码登录。 ## 相关文档 - [快速开始](QUICKSTART.md) - [生产运维](OPERATIONS.md) - [兼容性与升级](兼容性与升级.md) - [发布记录](CHANGELOG.md)