Files
vendoo/tools/verify-deployment-1.40.1.mjs
Masterluke77andGitHub 6f48827f4d Vendoo 1.41.2 – Git Ignore Boundary & Module Tracking Hotfix (#18)
* docs: prepare Vendoo 1.41.2 git-ignore boundary hotfix

* fix: track native source modules with root-anchored runtime ignores
2026-07-09 17:09:00 +02:00

156 lines
15 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { existsSync, lstatSync, readFileSync, readdirSync } from 'node:fs';
import { dirname, join, relative, sep } from 'node:path';
import { fileURLToPath } from 'node:url';
const root = dirname(dirname(fileURLToPath(import.meta.url)));
const read = rel => readFileSync(join(root, rel), 'utf8');
const failures = [];
const expect = (text, marker, label = marker) => { if (!text.includes(marker)) failures.push(`Fehlt: ${label}`); };
const forbid = (text, marker, label = marker) => { if (text.includes(marker)) failures.push(`Darf nicht enthalten sein: ${label}`); };
const pkg = JSON.parse(read('package.json'));
const lock = JSON.parse(read('package-lock.json'));
const manifest = JSON.parse(read('update-manifest.json'));
const html = read('public/index.html');
const app = read('public/app.js');
const bootstrap = read('bootstrap.mjs');
const configStore = read('lib/config-store.mjs');
const runtimePaths = read('lib/runtime-paths.mjs');
const setupPs = read('setup.ps1');
const setupGui = read('setup-gui.ps1');
const setupBat = read('setup.bat');
const setupSh = read('setup.sh');
const compose = read('compose.yaml');
const composeVps = read('compose.vps.yaml');
const caddy = read('deploy/Caddyfile');
const env = read('.env.example');
const gitignore = read('.gitignore');
const ci = read('.github/workflows/ci.yml');
const release = read('.github/workflows/release.yml');
const gitDeploy = read('scripts/github-deploy.ps1');
const gitSafety = read('tools/verify-git-safety.mjs');
const gitSafetyRegression = read('tools/verify-git-safety-regression.mjs');
const releaseBuilder = read('tools/build-release.mjs');
const installerShellGate = read('tools/verify-installer-shell.sh');
const backupScript = read('scripts/docker-backup.sh');
const restoreScript = read('scripts/docker-restore.sh');
const gitStaging = read('tools/prepare-git-staging.mjs');
const gitStagingRegression = read('tools/verify-git-staging.mjs');
const architectureGate = read('tools/verify-platform-architecture-1.40.0.mjs');
const themeGate = read('tools/verify-theme-manager-1.40.0.mjs');
const securityGate = read('tools/verify-security-foundation-1.40.0.mjs');
const identityGate = read('tools/verify-identity-settings-1.40.0.mjs');
const catalogGate = read('tools/verify-catalog-media-1.40.0.mjs');
const moduleGate = read('tools/verify-module-manager-1.40.0.mjs');
const esmExportGate = read('tools/verify-esm-export-contracts.mjs');
const fluxHotfixGate = read('tools/verify-flux-loop-hotfix-1.40.1.mjs');
const moduleManager = read('public/modules/module-manager/module-manager.js');
const moduleService = read('app/modules/module-manager/service.mjs');
const themeManager = read('public/modules/theme-manager/theme-manager.js');
const tokenSource = read('public/design-system/tokens/source.json');
const tokenCss = read('public/design-system/tokens.css');
const moduleSchema = read('app/contracts/module.schema.json');
const boundaries = read('app/architecture-boundaries.json');
for (const [label, value] of [
['package.json', pkg.version], ['package-lock.json', lock.version],
['package-lock root', lock.packages?.['']?.version], ['update-manifest', manifest.version],
]) if (value !== '1.40.1') failures.push(`${label}-Version ist ${value}`);
for (const marker of ['content="1.40.1"', 'style.css?v=1.40.1', 'app.js?v=1.40.1']) expect(html, marker, `UI-Build ${marker}`);
if (!app.startsWith("const VENDOO_UI_BUILD = '1.40.1';")) failures.push('UI-Build ist nicht 1.40.1');
for (const marker of ['VENDOO_CONFIG_PATH', "await import('./server.mjs')", 'override: true']) expect(bootstrap, marker, `Bootstrap ${marker}`);
for (const marker of ['CONFIG_PATH', 'writeRuntimeConfig', 'updateRuntimeConfig', 'mode: 0o600']) expect(configStore, marker, `Konfigurationsspeicher ${marker}`);
for (const marker of ['VENDOO_CONFIG_PATH', 'runtime_config: CONFIG_PATH', 'VENDOO_MODULES_DIR', 'module_state: MODULE_STATE_PATH']) expect(runtimePaths, marker, `Runtime-Pfade ${marker}`);
for (const marker of ["setSecret('LOCAL_IMAGE_TOKEN', token, { source: 'token-regeneration' })", 'runtime_config_path: CONFIG_PATH']) expect(read('server.mjs'), marker, `Server-Konfiguration ${marker}`);
for (const marker of ['readRuntimeConfig()', 'writeRuntimeConfig(envContent)', 'ALL_FIELDS', 'Unbekanntes Einstellungsfeld']) expect(read('app/modules/settings/service.mjs'), marker, `Settings-Modul ${marker}`);
forbid(read('server.mjs'), "join(__dirname, '.env')", 'direktes Schreiben in schreibgeschütztes App-.env');
for (const marker of ["$Version = '1.40.1'", '?build=1.40.1', "'install-local'", "'install-docker'", 'Configure-VendooConsole', 'Initialize-VendooEnvironment']) expect(setupPs, marker, `Windows-Setup ${marker}`);
for (const marker of ["foreach ($name in @('uploads','config','modules'))", "module-state\\modules-state.json", 'Modulpakete und Modulzustand wiederhergestellt']) expect(setupPs, marker, `Windows-Modul-Backup ${marker}`);
for (const marker of [
'Vendoo 1.40.1 Installation', 'Lokal auf diesem Windows-PC', 'Docker Desktop auf diesem Windows-PC',
'Set-Configuration', 'VENDOO_SETUP_TOKEN', 'Clipboard', 'AI- und Marktplatz-Schlüssel werden später',
]) expect(setupGui, marker, `Windows-GUI ${marker}`);
forbid(setupGui, 'PlaceholderText', 'nicht mit Windows PowerShell 5.1 kompatible PlaceholderText-Eigenschaft');
for (const marker of ['setup-gui.ps1', '-STA', 'Parser]::ParseFile']) expect(setupBat, marker, `setup.bat ${marker}`);
for (const marker of [
'Zero-Edit Deployment Assistant', 'configure_wizard', 'VPS / öffentlicher Server mit automatischem HTTPS',
'VENDOO_DOMAIN', 'compose.vps.yaml', 'Caddy übernimmt HTTPS automatisch', 'keine Datei musste manuell bearbeitet werden',
'Aktualisieren (mit Sicherheitsbackup)', 'docker-backup.sh',
]) expect(setupSh, marker, `Linux-Assistent ${marker}`);
for (const marker of ['VENDOO_CONFIG_PATH: /app/data/config/vendoo.env', 'vendoo_config:/app/data/config', 'vendoo_modules:/app/data/modules']) expect(compose, marker, `Basis-Compose-Konfiguration ${marker}`);
for (const marker of ['caddy:2-alpine', '80:80', '443:443', './deploy/Caddyfile', 'condition: service_healthy', 'read_only: true', 'vendoo_config:/app/data/config', 'vendoo_modules:/app/data/modules']) expect(composeVps, marker, `VPS-Compose ${marker}`);
for (const marker of ['{$VENDOO_DOMAIN}', 'reverse_proxy vendoo:8124', 'Strict-Transport-Security']) expect(caddy, marker, `Caddy ${marker}`);
for (const marker of ['VENDOO_DOMAIN=', 'VENDOO_SETUP_TOKEN=', 'VENDOO_COOKIE_SECURE=', 'LOCAL_IMAGE_ENABLED=false']) expect(env, marker, `.env.example ${marker}`);
for (const marker of ['name: Vendoo CI', 'npm ci', 'npm run verify:git', 'npm run verify:git-regression', 'npm run verify:git-staging', 'npm run verify:esm-exports', 'npm run verify:flux-loop', 'npm run verify:architecture', 'npm run verify:themes', 'npm run verify:modules', 'npm run verify:deployment', 'npm run verify:config', 'npm run verify:installer-shell', 'docker build --pull', 'compose.vps.yaml']) expect(ci, marker, `CI ${marker}`);
for (const marker of ['name: Vendoo Release', 'Release-Tag gegen Paketversion prüfen', 'npm run verify:git-staging', 'npm run verify:esm-exports', 'npm run verify:flux-loop', 'npm run verify:architecture', 'npm run verify:themes', 'npm run verify:modules', 'npm run verify:config', 'npm run verify:installer-shell', 'release-output', 'gh release upload', 'ghcr.io', 'docker/build-push-action@v6', 'actions/attest@v4', 'attestations: write', 'id-token: write', 'steps.push.outputs.digest', 'linux/amd64,linux/arm64']) expect(release, marker, `Release-Workflow ${marker}`);
for (const marker of ['release/1.40.1-flux-loop-hotfix', 'verify-git-safety.mjs', 'prepare-git-staging.mjs', 'RedirectStandardOutput', 'github-deploy-safety-report.txt', 'Zum Fortfahren PUSH eingeben', 'vendoo/pull/14']) expect(gitDeploy, marker, `GitHub-Deploy ${marker}`);
for (const marker of ['fileURLToPath', 'kompletten Arbeitsbaum', 'forbiddenPathPatterns', 'secretPatterns', 'Git-Sicherheitsgate erfolgreich']) expect(gitSafety, marker, `Git-Sicherheitsgate ${marker}`);
for (const marker of ['unversioniert', '.env.local', 'untracked-secret.txt', 'Git-Sicherheitsgate-Regressionstest erfolgreich']) expect(gitSafetyRegression, marker, `Git-Sicherheitsgate-Regression ${marker}`);
for (const marker of ['prepareGitStaging', 'shouldSkipStagingEntry', 'allowedEnvTemplates', 'skippedTopLevelDirs', 'operations', 'updates', 'Ziel ist kein geklontes Git-Repository']) expect(gitStaging, marker, `Git-Staging ${marker}`);
for (const marker of ['.env.local', 'operations/staging/job.json', 'updates/backups/slice22_1_20260707-194953/setup.ps1', '.git/marker', 'Git-Staging-Regressionstest erfolgreich']) expect(gitStagingRegression, marker, `Git-Staging-Regression ${marker}`);
for (const marker of ['release-output', 'FILE_CHECKSUMS_SHA256.txt', 'createHash', 'shouldSkipStagingEntry']) expect(releaseBuilder, marker, `Release-Builder ${marker}`);
for (const marker of ['run_mode docker', 'run_mode nas', 'run_mode vps', 'VENDOO_SETUP_TOKEN', 'stat -c']) expect(installerShellGate, marker, `Shell-Installer-Gate ${marker}`);
for (const marker of ['db uploads backups operations logs config modules', 'vendoo-data.tar.gz']) expect(backupScript, marker, `Docker-Backup ${marker}`);
for (const marker of ['db uploads backups operations logs config modules', '--confirm', 'docker-backup.sh']) expect(restoreScript, marker, `Docker-Restore ${marker}`);
for (const marker of ['.env', 'runtime/', 'modules/', 'updates/', 'local-ai/comfyui/', '.vendoo-install-mode', 'release-output/']) expect(gitignore, marker, `.gitignore ${marker}`);
for (const marker of ['createPlatformKernel', "id: 'platform.status.read'", "policy: 'platform.security-admin'", 'await platformKernel.stop()']) expect(read('server.mjs'), marker, `Platform-Kernel ${marker}`);
for (const marker of ['Platform-Architecture-Gate 1.40.1 erfolgreich', 'MODULE_DEPENDENCY_CYCLE', 'MODULE_DISABLED']) expect(architectureGate, marker, `Architektur-Gate ${marker}`);
for (const marker of ['Theme-Manager-Gate 1.40.1 erfolgreich', 'THEME_VALUE_INVALID', 'theme_profiles', 'user_theme_preferences']) expect(themeGate, marker, `Theme-Gate ${marker}`);
for (const marker of ['Security-Foundation-Gate 1.40.1 erfolgreich', 'SECRET_VALUE_INVALID', 'requestContextMiddleware']) expect(securityGate, marker, `Security-Gate ${marker}`);
for (const marker of ['Identity-&-Settings-Gate 1.40.1 erfolgreich', 'SESSION_NOT_OWNED', 'Unbekanntes Einstellungsfeld']) expect(identityGate, marker, `Identity-/Settings-Gate ${marker}`);
for (const marker of ['Catalog-&-Media-Gate 1.40.1 erfolgreich', 'LISTING_TRASH_NOT_FOUND', 'protectedPaths']) expect(catalogGate, marker, `Catalog-/Media-Gate ${marker}`);
for (const marker of ['Module-Manager-Gate 1.40.1 erfolgreich', 'MODULE_PROTECTED', 'MODULE_NOT_ACTIVATABLE', '.vmod-Import/Export']) expect(moduleGate, marker, `Modulmanager-Gate ${marker}`);
for (const marker of ['ESM-Export-Vertragsprüfung erfolgreich', 'collectExportsFromFile', 'importPattern']) expect(esmExportGate, marker, `ESM-Export-Gate ${marker}`);
for (const marker of ['FLUX-Loop-Hotfix-Gate 1.40.1 erfolgreich', 'stopFluxPromptJobLoop', 'verify:esm-exports']) expect(fluxHotfixGate, marker, `FLUX-Hotfix-Gate ${marker}`);
for (const marker of ['/api/admin/modules', 'dataset.moduleAction', 'module-manager-file', 'Deklarative Module sind aktivierbar']) expect(moduleManager, marker, `Modulmanager UI ${marker}`);
for (const marker of ['PROTECTED_MODULE_IDS', 'builtin-reference', 'MODULE_DISABLE_BEFORE_REMOVE', 'MODULE_EXTENSION_HOST_UNAVAILABLE']) expect(moduleService, marker, `Modulmanager Service ${marker}`);
for (const marker of ['/api/themes/preference', '/api/themes/system-default', 'previewTheme']) expect(themeManager, marker, `Theme Manager ${marker}`);
for (const marker of ['contractVersion', 'color.brand', 'density.controlHeight', 'motion.normal']) expect(tokenSource, marker, `Tokenquelle ${marker}`);
for (const marker of [':root {', '[data-theme="dark"]', '[data-theme="contrast"]', '--vd-brand:']) expect(tokenCss, marker, `Token-CSS ${marker}`);
for (const marker of ['Vendoo Module Manifest', 'legacy-bridge', 'extension-host']) expect(moduleSchema, marker, `Modulschema ${marker}`);
for (const marker of ['modular-monolith', 'denyImplicitRoutes', 'thirdPartyExtensionsInMainProcess', 'strangler']) expect(boundaries, marker, `Architekturgrenzen ${marker}`);
for (const required of ['app/kernel/platform-kernel.mjs', 'app/kernel/module-registry.mjs', 'app/kernel/route-registry.mjs', 'app/kernel/policy-engine.mjs', 'app/kernel/input-schema.mjs', 'app/core/themes/theme-contract.mjs', 'app/core/security/secret-contract.mjs', 'app/modules/security/index.mjs', 'lib/secret-store.mjs', 'lib/structured-logger.mjs', 'public/design-system/theme-runtime.js', 'public/design-system/theme-contract.json', 'public/core/frontend-module-registry.js', 'public/core/safe-dom.js', 'public/core/api-client.js', 'docs/architecture/MODULE_SYSTEM_1_35_0.md', 'docs/architecture/DESIGN_SYSTEM_1_35_0.md', 'docs/architecture/SECURITY_ARCHITECTURE_1_35_0.md', 'docs/architecture/THEME_MANAGER_1_36_0.md', 'docs/architecture/MODULE_MANAGER_1_40_0.md', 'app/core/modules/module-package-contract.mjs', 'app/core/modules/module-package-store.mjs', 'app/core/modules/module-state-store.mjs', 'app/modules/module-manager/routes.mjs', 'public/modules/module-manager/module-manager.js']) if (!existsSync(join(root, required))) failures.push(`Architektur-Pflichtdatei fehlt: ${required}`);
for (const marker of ['read_only: true', 'no-new-privileges:true', 'cap_drop:', '/readyz', 'host.docker.internal:host-gateway']) expect(compose, marker, `Basis-Compose ${marker}`);
for (const required of [
'.github/workflows/ci.yml', '.github/workflows/release.yml', '.github/dependabot.yml', '.github/CODEOWNERS',
'GitHub-Deploy-Assistent.bat', 'scripts/github-deploy.ps1', 'scripts/github-deploy.sh',
'setup-gui.ps1', 'bootstrap.mjs', 'lib/config-store.mjs', 'compose.vps.yaml', 'deploy/Caddyfile', 'tools/verify-git-safety.mjs', 'tools/verify-git-safety-regression.mjs', 'tools/prepare-git-staging.mjs', 'tools/verify-git-staging.mjs', 'tools/verify-installer-shell.sh', 'tools/build-release.mjs', 'tools/verify-esm-export-contracts.mjs', 'tools/verify-flux-loop-hotfix-1.40.1.mjs',
]) if (!existsSync(join(root, required))) failures.push(`Pflichtdatei fehlt: ${required}`);
function walk(dir, out = []) {
for (const name of readdirSync(dir)) {
if (name === 'node_modules' || name === 'release-output' || name === '.git') continue;
const abs = join(dir, name);
const rel = relative(root, abs).split(sep).join('/');
const stat = lstatSync(abs);
if (stat.isDirectory()) walk(abs, out); else out.push(rel);
}
return out;
}
const files = walk(root);
const forbiddenRuntime = files.filter(rel =>
rel === '.env' || rel === '.vendoo-install-mode' ||
/(^|\/)(runtime|node_modules|uploads|backups|logs|updates)(\/|$)/i.test(rel) || /^modules\//i.test(rel) ||
/^db\/.*\.(db|sqlite|sqlite3)(-wal|-shm)?$/i.test(rel) ||
/^local-ai\/(comfyui|downloads|extract-temp)\//i.test(rel)
);
if (forbiddenRuntime.length) failures.push(`Verbotene Laufzeitdaten im Paket: ${forbiddenRuntime.slice(0, 10).join(', ')}`);
forbid(read('README.md'), '.env.example` nach `.env` kopieren', 'alte manuelle .env-Anweisung im README');
if (failures.length) {
console.error(`Deployment-Gate 1.40.1 fehlgeschlagen (${failures.length}):`);
failures.forEach(item => console.error(`- ${item}`));
process.exit(1);
}
console.log('Deployment-Gate 1.40.1 erfolgreich: FLUX-Lifecycle-Hotfix, ESM-Exportverträge, 14 native Module, sicherer Modulmanager, Zero-Edit-Installer, CI und Release-Workflow geprüft.');