status: done created: 2026-07-26
/apply 前先运行 Starter Crypto 现有测试和相关模块编译,记录真实基线。| 项目 | 值 |
|---|---|
| JUnit 版本 | JUnit Jupiter 5,由 Spring Boot 3.5.13 BOM 管理 |
| Mock 框架 | Mockito + AssertJ/JUnit Assertions |
| 现有测试基线 | Starter Crypto 1 个测试类/3 条;Starter Config 无测试目录;Generator 有既有专项测试,Data 暂无加密专项测试 |
| 数据访问验证 | Mockito/测试 JdbcTemplate + Mapper XML/SQL 合同测试;有隔离测试库时再做可选 E2E |
| 前端验证 | Node v20.19.0 + pnpm build,本次 UI 仅删除字段,不做视觉改版 |
CryptoConfigurationValidator| 场景 | 配置 | 预期结果 |
|---|---|---|
| 传输加密启用且根密钥空 | enabled=true |
启动校验失败并指出 FORGE_CRYPTO_SECRET_KEY |
| 根密钥非法 Base64/错误长度 | 任一启用路径 | 启动校验失败,不回显配置值 |
| 兼容写入 | writeVersioned=false |
要求旧格式写入密钥,不要求活动 key |
| 版本化写入 | writeVersioned=true |
要求合法 activeKeyId 和活动 key |
| 历史 keyring | 合法/非法 keyId、重复/空 key | 合法通过,非法失败 |
| 全部能力关闭 | 不配置密钥 | 不因无关密钥失败 |
CryptoSecretEnvironmentPostProcessor| 场景 | 输入 | 预期结果 |
|---|---|---|
| 首次新安装 | 无显式根密钥、密钥文件不存在 | 原子生成两个独立 16 字节 Base64 密钥,注入 Spring Environment |
| 重启 | 密钥文件已存在 | 复用全部原值,文件不重写 |
| 显式配置 | 环境/JVM 提供非空根密钥 | 跳过自动生成,不创建文件 |
| 损坏文件 | 缺少必需字段、非法 Base64 或错误长度 | 启动失败,不重生成 |
| 权限 | POSIX 文件系统 | 目录 0700、密钥文件 0600 |
| 空白 Compose 变量 | 容器传入空字符串 | 按未配置处理,由密钥文件值覆盖空白值 |
VersionedPersistentCryptoService| 场景 | 输入 | 预期结果 |
|---|---|---|
| 兼容写 | writeVersioned=false |
输出旧无版本 Base64,可被旧/新服务读取 |
| 活动 key 写 | writeVersioned=true |
输出 FPC1:算法:keyId:payload,不含明文 |
| 活动 key 读 | 当前 keyId | 正确解密 |
| 历史 key 读 | 轮换前 keyId | 正确解密,新写仍使用活动 keyId |
| 旧密文读 | legacy key + legacy algorithm | 正确解密 |
| 未知 keyId | 合法格式但 key 不存在 | 失败关闭 |
| 头/算法/payload 损坏 | 多种非法输入 | 失败关闭,不返回原值 |
| 缺旧钥 | 无版本密文 | 失败关闭 |
| null/空值 | null/空字符串 | 按接口合同原样处理,不误分类 |
| 重加密 | 旧/历史/活动格式 | 旧和历史转活动;活动格式保持幂等 |
CryptoConfigExposureTest / CryptoConfigSanitizerTest| 场景 | 输入 | 预期结果 |
|---|---|---|
| 管理 GET | crypto 配置 | JSON 不含根密钥、RSA 私钥、activeKey、keys、legacyKey |
| 管理 PUT | 非敏感开关 | 正常保存并同步 |
| 管理 PUT | 敏感字段 | 明确拒绝,不写数据库 |
| ConfigConverter | 含历史敏感字段 JSON | 属性 map 不产生部署级密钥键 |
| 通用 group list/page/detail | crypto 原始 JSON | 返回前完成清洗 |
| 通用 group add/edit | 含敏感字段 | 明确拒绝 |
| 散配置 add/edit/改名 | 部署级 crypto key | 明确拒绝,不写数据库 |
| 普通敏感散配置 | 文件存储等既有配置 | 继续使用既有掩码保留语义,不扩大禁用范围 |
| 非 crypto 分组 | 普通 JSON | 不受敏感清洗误伤 |
V1.0.52 且仓库无重复版本。sys_config 删除目标覆盖根密钥、RSA 私钥和 persistence keyring。sys_config_group 只清理 group_code='crypto' 的敏感 JSON 路径。${...} Flyway 占位符。DataConnectionCryptoLifecycleTest| 场景 | 输入/Mock | 预期结果 |
|---|---|---|
| 新增密码 | 版本化写开启 | 保存 FPC1,不保存明文 |
| 修改空密码 | 已有密文 | 保留原密文 |
| 读取旧密码 | legacy 密文 | JDBC 获得明文密码 |
| 读取新密码 | active/historical | JDBC 获得明文密码 |
| 错误 key/损坏密文 | 解密抛异常 | 连接创建失败,不把密文当密码 |
DataConnectionCryptoMigrationServiceTest| 场景 | 预期结果 |
|---|---|
| inventory | 仅计数分类,不返回敏感值 |
| dry-run | 不执行 UPDATE |
| execute | 旧格式变活动格式,更新条件含 id + 原密文 |
| 并发修改 | 条件更新 0 行,计冲突,不覆盖新值 |
| 重复执行 | 活动格式跳过,结果幂等 |
| 单行失败 | 批次回滚/失败计数,其他批次按合同继续 |
DynamicCrudCryptoLifecycleTest| 场景 | 输入 | 预期结果 |
|---|---|---|
| SM4/AES 写入 | camelCase 配置 + snake_case 数据 | 指定列写版本化密文 |
| 旧/活动/历史读取 | 多字段混合 | 全部正确解密 |
| 非字符串/空字段 | null/数字/空串 | 按既有合同跳过 |
| 非法算法/未知 keyId/损坏值 | 任一字段 | 当前操作失败,不返回或落库原值 |
| encrypt_config 非法 | 非对象/字段规则非法 | 明确业务错误 |
LowcodeCryptoMigrationServiceTest| 场景 | 预期结果 |
|---|---|
| 未显式 configKey | 拒绝执行 |
| 主库/外部库 | 使用对应 RuntimeJdbcTemplate 与方言 |
| 数据源只读 | BLOCKED,不执行写入 |
| 表/字段不存在 | BLOCKED |
| 非单主键/非法标识符 | BLOCKED |
| 列容量不足 | BLOCKED,不自动 DDL |
| dry-run | 返回分类和容量结果,不 UPDATE |
| execute | 参数化批次更新,按当前租户,原值比较 |
| 重跑/并发冲突 | 幂等并正确计数 |
ConfigManageController 只允许平台管理员调用 migration API。dryRun=true;expectedActiveKeyId 不匹配时拒绝。PersistentCryptoService 和 Data 插件依赖。EncryptTypeHandler 和 SysClient 死引用清零。CryptoRuntimeConfig/SessionKeyStore 仍存在,API 会话协议未被误删。git diff --check。| 时间 | 范围 | 命令 | 结果 | 备注 |
|---|---|---|---|---|
| 2026-07-26 | 阶段一 Admin 聚合 | JDK 17 Admin 43 模块 package | 通过 | 复用 framework-captcha-security-hardening/execution-log.md |
| 2026-07-26 | 阶段一前端 | Node 20.19.0 pnpm build |
通过 | 8725 模块,存在既有 Vite 警告 |
| 2026-07-26 18:54 CST | 本 Proposal | 文档结构、行尾/EOF、敏感值扫描 | 通过 | HARD-GATE 前不运行代码测试 |
| 时间 | 变更范围 | 必跑项 | 实际命令 | 结果 | 跳过/警告 |
|---|---|---|---|---|---|
| 2026-07-26 18:54 CST | Proposal 文档 | 行尾/EOF、章节/状态一致性、历史密钥精确扫描 | rg + tail/od + 章节断言 |
通过 | 四份文件均以换行结束,无尾随空白,不含两处已知硬编码密钥值;仅文档,不运行代码测试 |
| 2026-07-26 21:22-21:53 CST | 配置、协议、数据连接、低代码和迁移入口 | Red/Green 与批次事务回归 | Reactor test-compile + /tmp/ForgeJUnitRunner 隔离矩阵 |
通过 | Red 捕获 2 条批次原子性失败和 1 条非法 JSON 失败;修复后批次事务 12 条及各目标组通过 |
| 2026-07-26 22:02 CST | 最终目标测试 | Config、Crypto、Data、Generator/System/Admin | Reactor 当前 target/classes 隔离执行 |
通过 | Config 8、Crypto 22、Data 7、Generator/System/Admin 22,共 59 条,0 失败 |
| 2026-07-26 22:02 CST | Admin/Report 测试编译 | 44 模块 -Penable-tests -DskipTests test-compile |
JDK 17 Maven Reactor | 通过 | 44/44 SUCCESS;测试源码全部编译 |
| 2026-07-26 22:07 CST | Admin UI | Node 20.19.0 pnpm build |
Vite 生产构建 | 通过 | 8725 模块,1 分 33 秒;保留既有组件命名、CSS 注释和分块警告 |
| 2026-07-26 22:08 CST | Admin/Report 聚合包 | mvn -pl forge-admin-server,forge-report-server -am package -DskipTests |
JDK 17 Maven Reactor | 通过 | 44/44 SUCCESS,38.178 秒 |
| 2026-07-26 22:09 CST | 最终静态安全证据 | 敏感值、Flyway、初始化 SQL、死代码、协议保留、diff | rg/find/git diff --check |
通过 | 受管范围历史根密钥和旧种子密文均 0;Flyway 无重复/占位符;SessionKeyStore 链路保留 |
| 2026-07-27 | Task 13 启动引导 | 首启/重启/显式优先/空变量/损坏/并发/权限/SpringApplication 自动注册 | Starter Crypto Reactor 目标测试 | 通过 | 自动引导 8/8;与原配置校验合计 15/15;不启动真实服务 |
| 2026-07-27 | Docker 密钥持久化 | Compose 环境变量与 crypto_secrets 命名卷 |
docker compose config --quiet |
通过 | 未构建镜像、未启动容器 |
forge-starter-crypto jar,目标测试编译失败;最终证据使用已成功编译的 Reactor target/classes 置于 classpath 首位执行。test 仍受仓库既有 Surefire groups/excludedGroups 与测试引擎配置影响;44 模块 test-compile 和隔离 JUnit 结果已分别覆盖编译与行为。execution-log.md:逐 Task 追加命令、关键输出、失败根因和跳过项。/api/config/manage/crypto、/api/config/group/**、crypto migration inventory/execute、数据连接和低代码既有 CRUD。sys_config/sys_config_group 敏感字段清理,password_cipher 和动态字段格式分类;真实结果仅在隔离测试库/生产变更单留档。