feat(hardening): 内嵌产品配置 + 系统级状态 + 全量 i18n + 依赖治理 + 资料清理

update-client-hardening 四工作流合入(构建/静态检查已过):

- 配置:不可变产品策略经 UpdateClientResources.cmake 归一化校验后
  内嵌 qrc(URL/相对路径/主程序必须落 install_root/版本/UUID 格式,
  CMake override 写入前复验);可变机器状态迁系统级原生存储;
  运行目录不再落可编辑 app_config.json。
- i18n:生产源全英文(no-Han 检查 41/41),中文进 translations/
  zh_CN 目录;翻译加载收敛 Common/TranslationHelper 唯一入口;
  Bootstrap 补资源文件。
- 依赖:Qt/OpenSSL/架构/Perl 机器路径改 imported targets +
  UpdateClientDependencies.cmake,3rdparty 由父工程契约供给。
- 清理:旧 README/SDK README/3 个重复 PowerShell 打包脚本/PDF 提取
  文本删除,canonical README + 5 份结构化英文文档替代;Launcher
  requireAdministrator manifest;统一 MSVC /utf-8 删运行时编码设置。
This commit is contained in:
Comely
2026-07-10 00:38:23 -07:00
parent b06e003502
commit fe5aa5bbf0
45 changed files with 5033 additions and 4083 deletions
+82
View File
@@ -0,0 +1,82 @@
cmake_minimum_required(VERSION 3.20)
if(NOT UPDATE_CLIENT_SCAN_ROOT)
message(FATAL_ERROR "UPDATE_CLIENT_SCAN_ROOT is required.")
endif()
cmake_path(
ABSOLUTE_PATH UPDATE_CLIENT_SCAN_ROOT
NORMALIZE
OUTPUT_VARIABLE _scan_root
)
if(NOT IS_DIRECTORY "${_scan_root}")
message(FATAL_ERROR "Production source scan root does not exist: ${_scan_root}")
endif()
file(GLOB_RECURSE _all_files LIST_DIRECTORIES FALSE "${_scan_root}/*")
set(_production_files)
foreach(_candidate IN LISTS _all_files)
cmake_path(CONVERT "${_candidate}" TO_CMAKE_PATH_LIST _normalized_candidate NORMALIZE)
cmake_path(
RELATIVE_PATH _normalized_candidate
BASE_DIRECTORY "${_scan_root}"
OUTPUT_VARIABLE _relative_candidate
)
string(TOLOWER "${_relative_candidate}" _candidate_lower)
if(_candidate_lower MATCHES
"(^|/)(translations|docs|out|build|generated|cmake-build[^/]*|\\.git)(/|$)")
continue()
endif()
if(_candidate_lower STREQUAL "bootstrap/bootstrap.rc")
continue()
endif()
cmake_path(GET _normalized_candidate FILENAME _file_name)
cmake_path(GET _normalized_candidate EXTENSION _file_extension)
string(TOLOWER "${_file_extension}" _file_extension)
if(NOT _file_name STREQUAL "CMakeLists.txt"
AND NOT _file_extension MATCHES
"^\\.(c|cc|cpp|cxx|h|hh|hpp|cmake|ui|qrc|manifest|rc|json)$")
continue()
endif()
list(APPEND _production_files "${_candidate}")
endforeach()
set(_han_utf8_regex
"(e3:[9ab][0-9a-f]:[89ab][0-9a-f]:"
"|e[4-9]:[89ab][0-9a-f]:[89ab][0-9a-f]:"
"|ef:a[4-9ab]:[89ab][0-9a-f]:"
"|f0:a[0-9a-f]:[89ab][0-9a-f]:[89ab][0-9a-f]:"
"|f0:b[01]:[89ab][0-9a-f]:[89ab][0-9a-f]:)"
)
string(JOIN "" _han_utf8_regex ${_han_utf8_regex})
set(_violations)
foreach(_production_file IN LISTS _production_files)
file(READ "${_production_file}" _file_hex HEX)
string(TOLOWER "${_file_hex}" _file_hex)
string(REGEX REPLACE "([0-9a-f][0-9a-f])" "\\1:" _file_bytes "${_file_hex}")
if(_file_bytes MATCHES "${_han_utf8_regex}")
cmake_path(
RELATIVE_PATH _production_file
BASE_DIRECTORY "${_scan_root}"
OUTPUT_VARIABLE _relative_file
)
list(APPEND _violations "${_relative_file}")
endif()
endforeach()
if(_violations)
list(JOIN _violations "\n " _violation_list)
message(FATAL_ERROR
"Han characters are forbidden in update-client production sources:\n"
" ${_violation_list}\n"
"Move user-visible text to the Qt translation catalog or the approved "
"Bootstrap STRINGTABLE resource."
)
endif()
list(LENGTH _production_files _production_file_count)
message(STATUS
"No-Han production source check passed (${_production_file_count} files)."
)