status: complete baseline-created: 2026-07-26
sdd/framework-hardening-phased。forge-starter-message 已提供 MessageClient 与 SmsMessageChannel,forge-plugin-system 同时依赖 Auth 与 Message,适合作为发送 SPI 的组合实现层。CaptchaServiceImpl 两个 import 和新增 CaptchaProperties.java,未回退、未覆盖。/apply framework-captcha-security-hardening。2026-07-26 15:29:28 CST 回复“开始”,明确批准阶段一 Spec。propose 更新为 apply,Tasks/Test Spec 状态同步进入实施阶段。JAVA_HOME=/opt/homebrew/Cellar/openjdk@17/17.0.13/libexec/openjdk.jdk/Contents/Home PATH=/opt/homebrew/Cellar/openjdk@17/17.0.13/libexec/openjdk.jdk/Contents/Home/bin:$PATH mvn -Penable-tests -pl forge-framework/forge-starter-parent/forge-starter-auth -am test。BUILD SUCCESS,Auth Starter 现有 2 个测试类共 7 条用例通过,0 失败、0 错误、0 跳过。forge-starter-outbound 48 条、forge-flow-client 11 条用例通过,均为 0 失败、0 错误、0 跳过。SliderCaptchaResult、SmsCaptchaResult 存在既有 Lombok @Builder 默认值警告;不阻断本阶段基线,Task 1 不扩大处理范围。code 字段增加 NON_NULL 序列化规则,补充默认关闭的 CaptchaProperties.devEchoCode,新增 Auth Starter 内部 SmsCaptchaSender SPI。mvn -Penable-tests -pl forge-framework/forge-starter-parent/forge-starter-auth -am test -Dtest=CaptchaResponseSerializationTest -Dsurefire.failIfNoSpecifiedTests=false。\"code\":null,符合预期失败原因。BUILD SUCCESS,3 条通过,0 失败、0 错误、0 跳过。mvn -pl forge-framework/forge-starter-parent/forge-starter-auth -am compile -DskipTests;结果 BUILD SUCCESS。git diff --check 返回 0。mvn -Penable-tests -pl forge-framework/forge-starter-parent/forge-starter-auth -am test -Dtest=CaptchaServiceImplTest -Dsurefire.failIfNoSpecifiedTests=false。testCompile 按预期失败,现有 CaptchaServiceImpl 只有单参数构造器,尚无配置、Profile 和 Sender 边界。CaptchaServiceImplTest 10 条通过,覆盖默认/dev/prod 回显、Sender 缺失/失败/异常/成功、缓存回滚、开发模拟和短信一次性校验。mvn -Penable-tests -pl forge-framework/forge-starter-parent/forge-starter-auth -am test;结果 BUILD SUCCESS,Auth Starter 20 条通过,0 失败、0 错误、0 跳过。codeStr/cacheCode/correctX/moveX/expectedX/code 的日志参数,结果无匹配;全部 6 处手机号日志均显式调用 SensitiveDataUtil.maskPhone。git diff --check 返回 0。MessageSmsCaptchaSender,通过 MessageClient 向 SMS 通道发送单手机号验证码;手机号登录统一调用 validateAndDeleteSmsCaptcha,复用 captcha:sms:<phone> 一次性校验协议。mvn -Penable-tests -pl forge-framework/forge-plugin-parent/forge-plugin-system -am test -Dtest=MessageSmsCaptchaSenderTest,UserLoadServiceImplCaptchaTest -Dsurefire.failIfNoSpecifiedTests=false。forge-starter-datascope Surefire 配置截断,错误为 groups/excludedGroups require TestNG, JUnit48+ or JUnit 5;未将该上游问题误记为目标用例预期失败,也未越界修改 datascope。mvn -pl forge-framework/forge-plugin-parent/forge-plugin-system -am install -DskipTests 执行成功,25 个 Reactor 模块全部 BUILD SUCCESS。forge-server Reactor 根目录执行 mvn -Penable-tests -pl forge-framework/forge-plugin-parent/forge-plugin-system test -Dtest=MessageSmsCaptchaSenderTest,UserLoadServiceImplCaptchaTest,结果 BUILD SUCCESS,4 条通过,0 失败、0 错误、0 跳过。mvn -Penable-tests -pl forge-framework/forge-plugin-parent/forge-plugin-system test,结果 BUILD SUCCESS,当前模块全部 4 条测试通过,主代码和测试代码编译成功。SensitiveDataUtil.maskPhone(phone)、异常类型和固定消息 SMS_CHANNEL_OPERATION_FAILED 的安全化堆栈,不输出验证码、完整手机号或供应商原始异常消息;git diff --check 返回 0。MessageClient Stub 覆盖,真实通道 E2E 留给用户侧配置环境验收。FORGE_CAPTCHA_DEV_ECHO_CODE 且默认 false;登录页删除图形和短信验证码答案的控制台输出;业务提示、图片、codeKey 和倒计时逻辑保持不变。mvn -Penable-tests -pl forge-framework/forge-starter-parent/forge-starter-auth,forge-framework/forge-plugin-parent/forge-plugin-system -am test。Auth 20 条、Outbound 48 条、Flow Client 11 条及 Excel/File 相关上游测试通过;随后在第 20/25 个模块 forge-starter-datascope 因既有 groups/excludedGroups require TestNG, JUnit48+ or JUnit 5 失败,System 在该命令中被跳过。System 本阶段已有独立 4 条完整测试通过证据,未修改无关 datascope。mvn -pl forge-admin-server -am package -DskipTests,结果 BUILD SUCCESS,43 个 Reactor 模块全部打包成功,包含 Auth、Message、System 和 Admin。v20.19.0 下执行 NODE_OPTIONS=--max-old-space-size=8192 pnpm build,结果成功,8725 个模块完成转换,耗时 1 分 44 秒。UserSelectModal 组件命名冲突、动态/静态 import 混用、CSS // 注释和分块提示;本次只删除登录页控制台副作用,警告与本轮差异无关且不阻断构建。forge-admin-server/target/classes/application.yml,确认 forge.captcha.dev-echo-code 为 ${FORGE_CAPTCHA_DEV_ECHO_CODE:false};Ruby 同时提示 /opt/homebrew/opt 目录权限警告,不影响解析结果。expectedX 局部变量,未将其误判为泄露;改用 rg --pcre2 精确扫描 res.data.code(排除 codeKey)、验证码 console.warn 以及日志中的 codeStr/cacheCode/correctX/moveX/expectedX,结果无匹配。git diff --check 返回 0;打包产物目录未进入版本控制差异。