diff --git a/vehicle-data-platform/apps/web/index.html b/vehicle-data-platform/apps/web/index.html
index 83c5c03e..dc84da70 100644
--- a/vehicle-data-platform/apps/web/index.html
+++ b/vehicle-data-platform/apps/web/index.html
@@ -4,9 +4,55 @@
车辆数据管理中台
+
-
+
+
+
diff --git a/vehicle-data-platform/apps/web/scripts/verify-build.mjs b/vehicle-data-platform/apps/web/scripts/verify-build.mjs
index da7eb9ad..1f07add1 100644
--- a/vehicle-data-platform/apps/web/scripts/verify-build.mjs
+++ b/vehicle-data-platform/apps/web/scripts/verify-build.mjs
@@ -8,6 +8,7 @@ const mileageWorkers = assets.filter((name) => /^mileageExport\.worker-[\w-]+\.j
const monitorAssets = assets.filter((name) => /^MonitorPage-[\w-]+\.js$/.test(name));
const runtimeConfig = readFileSync(resolve(process.cwd(), 'dist/app-config.js'), 'utf8');
const safeRuntimeTemplate = readFileSync(resolve(process.cwd(), 'public/app-config.example.js'), 'utf8');
+const builtIndex = readFileSync(resolve(process.cwd(), 'dist/index.html'), 'utf8');
const releaseManifest = readFileSync(resolve(process.cwd(), 'dist/.release-assets'), 'utf8').split(/\r?\n/).filter(Boolean);
if (excelAssets.length !== 1) {
@@ -22,6 +23,16 @@ if (monitorAssets.length !== 1) {
if (runtimeConfig !== safeRuntimeTemplate) {
throw new Error('production dist/app-config.js must match the credential-free runtime template');
}
+if (!builtIndex.includes('id="platform-boot"')
+ || !builtIndex.includes('vehicle-platform:ready')
+ || !builtIndex.includes('window.setTimeout(fail, 10_000)')) {
+ throw new Error('production index must retain the static boot recovery boundary');
+}
+const mainAsset = builtIndex.match(/