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
+50 -18
View File
@@ -1,7 +1,5 @@
#include <Windows.h>
#include <QApplication>
#include <QDebug>
#include <QTextCodec>
#include <QMessageBox>
#include <QDir>
#include <QFileInfo>
@@ -13,13 +11,14 @@
#include "../Common/TicketHelper.h"
#include "../Common/IntegrityHelper.h"
#include "../Common/DeviceIdentityHelper.h"
#include "../Common/TranslationHelper.h"
int main(int argc, char* argv[])
{
SetConsoleOutputCP(936);
QTextCodec::setCodecForLocale(QTextCodec::codecForName("GBK"));
QApplication a(argc, argv);
QApplication::setApplicationName("Marsco MainApp");
TranslationHelper translation;
translation.installForSystemLocale();
qDebug() << Qt::endl << "entered main app" << Qt::endl;
@@ -44,8 +43,9 @@ int main(int argc, char* argv[])
config.getValue("App", "current_version"), config.getValue("App", "launch_token"),
&ticketError))
{
QMessageBox::critical(nullptr, "Startup Restriction",
QString("Invalid or missing one-time launch ticket: %1\nPlease use %2.")
QMessageBox::critical(nullptr,
QCoreApplication::translate("MainApp", "Startup Restriction"),
QCoreApplication::translate("MainApp", "Invalid or missing one-time launch ticket: %1\nPlease use %2.")
.arg(ticketError, launcherExecutable));
return -1;
}
@@ -55,48 +55,76 @@ int main(int argc, char* argv[])
DeviceIdentityHelper identity(appDir);
if (!identity.verifyLocal(config.getValue("App", "app_id"), config.getValue("App", "channel")))
{
QMessageBox::critical(nullptr, "License Error", QString("Local license invalid: %1").arg(identity.errorString()));
QMessageBox::critical(nullptr,
QCoreApplication::translate("MainApp", "License Error"),
QCoreApplication::translate("MainApp", "Local license invalid: %1").arg(identity.errorString()));
return -1;
}
PolicyHelper policy(appDir);
if (!policy.loadPolicy("config/version_policy.dat") || !policy.isValid())
{
QMessageBox::critical(nullptr, "Policy Error", QString("Local policy invalid: %1").arg(policy.errorString()));
QMessageBox::critical(nullptr,
QCoreApplication::translate("MainApp", "Policy Error"),
QCoreApplication::translate("MainApp", "Local policy invalid: %1").arg(policy.errorString()));
return -1;
}
if (policy.isExpired())
{
QMessageBox::critical(nullptr, "Policy Error", "Policy expired, cannot start the application.");
QMessageBox::critical(nullptr,
QCoreApplication::translate("MainApp", "Policy Error"),
QCoreApplication::translate("MainApp", "Policy expired. The application cannot start."));
return -1;
}
const QString currentVersion = config.getValue("App", "current_version");
if (!policy.isApplicable(config.getValue("App", "app_id"),
config.getValue("App", "channel"),
currentVersion)
|| !policy.allowRun() || !policy.isVersionAllowed(currentVersion))
{
QMessageBox::critical(
nullptr,
QCoreApplication::translate("MainApp", "Policy Error"),
QCoreApplication::translate(
"MainApp",
"The signed policy does not allow this installed version to run."));
return -1;
}
LocalStateHelper state(appDir);
if (!state.loadState())
{
QMessageBox::critical(nullptr, "State Error", QString("Cannot load local state: %1").arg(state.errorString()));
QMessageBox::critical(nullptr,
QCoreApplication::translate("MainApp", "State Error"),
QCoreApplication::translate("MainApp", "Cannot load local state: %1").arg(state.errorString()));
return -1;
}
if (state.isPolicySeqRolledBack(policy.policySeq()))
{
QMessageBox::critical(nullptr, "Policy Error", "Detected policy sequence rollback, startup blocked.");
QMessageBox::critical(nullptr,
QCoreApplication::translate("MainApp", "Policy Error"),
QCoreApplication::translate("MainApp", "A policy sequence rollback was detected, so startup was blocked."));
return -1;
}
if (state.isSystemTimeRewound())
{
QMessageBox::critical(nullptr, "Policy Error", "System time appears to be rewound, startup blocked.");
QMessageBox::critical(nullptr,
QCoreApplication::translate("MainApp", "Policy Error"),
QCoreApplication::translate("MainApp", "The system clock appears to have moved backward, so startup was blocked."));
return -1;
}
IntegrityHelper integrity(installRoot);
if (!integrity.verifyInstalledVersion(
config.getValue("App", "app_id"), config.getValue("App", "channel"),
config.getValue("App", "current_version")))
currentVersion))
{
QMessageBox::critical(nullptr, "Integrity Check Failed",
QString("Application files failed signed Manifest verification:\n%1")
QMessageBox::critical(nullptr,
QCoreApplication::translate("MainApp", "Integrity Check Failed"),
QCoreApplication::translate("MainApp", "Application files failed signed manifest verification:\n%1")
.arg(integrity.errorString()));
return -1;
}
@@ -107,7 +135,9 @@ int main(int argc, char* argv[])
state.updateAfterSuccessfulRun(ConfigHelper::instance().getValue("App", "current_version"), policy.policySeq());
if (!state.saveState())
{
QMessageBox::critical(nullptr, "State Error", QString("Cannot save local state: %1").arg(state.errorString()));
QMessageBox::critical(nullptr,
QCoreApplication::translate("MainApp", "State Error"),
QCoreApplication::translate("MainApp", "Cannot save local state: %1").arg(state.errorString()));
return -1;
}
@@ -120,7 +150,9 @@ int main(int argc, char* argv[])
|| healthFile.write(healthy) != healthy.size()
|| !healthFile.commit())
{
QMessageBox::critical(nullptr, "Startup Error", "Cannot write update health confirmation file.");
QMessageBox::critical(nullptr,
QCoreApplication::translate("MainApp", "Startup Error"),
QCoreApplication::translate("MainApp", "Cannot write the update health confirmation file."));
return -1;
}
}