* docs: prepare Vendoo 1.41.2 git-ignore boundary hotfix * fix: track native source modules with root-anchored runtime ignores
140 lines
13 KiB
JavaScript
140 lines
13 KiB
JavaScript
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.37.0.mjs');
|
||
const themeGate = read('tools/verify-theme-manager-1.37.0.mjs');
|
||
const securityGate = read('tools/verify-security-foundation-1.37.0.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.37.0') failures.push(`${label}-Version ist ${value}`);
|
||
|
||
for (const marker of ['content="1.37.0"', 'style.css?v=1.37.0', 'app.js?v=1.37.0']) expect(html, marker, `UI-Build ${marker}`);
|
||
if (!app.startsWith("const VENDOO_UI_BUILD = '1.37.0';")) failures.push('UI-Build ist nicht 1.37.0');
|
||
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']) expect(runtimePaths, marker, `Runtime-Pfade ${marker}`);
|
||
for (const marker of ['readRuntimeConfig()', 'writeRuntimeConfig(envContent)', "setSecret('LOCAL_IMAGE_TOKEN', token, { source: 'token-regeneration' })", 'runtime_config_path: CONFIG_PATH']) expect(read('server.mjs'), marker, `Server-Konfiguration ${marker}`);
|
||
forbid(read('server.mjs'), "join(__dirname, '.env')", 'direktes Schreiben in schreibgeschütztes App-.env');
|
||
|
||
for (const marker of ["$Version = '1.37.0'", '?build=1.37.0', "'install-local'", "'install-docker'", 'Configure-VendooConsole', 'Initialize-VendooEnvironment']) expect(setupPs, marker, `Windows-Setup ${marker}`);
|
||
|
||
for (const marker of [
|
||
'Vendoo 1.37.0 – 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']) 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']) 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:architecture', 'npm run verify:themes', '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:architecture', 'npm run verify:themes', '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.37.0-security-foundation', 'verify-git-safety.mjs', 'prepare-git-staging.mjs', 'RedirectStandardOutput', 'github-deploy-safety-report.txt', 'Zum Fortfahren PUSH eingeben', 'vendoo/pull/10']) 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', 'vendoo-data.tar.gz']) expect(backupScript, marker, `Docker-Backup ${marker}`);
|
||
for (const marker of ['db uploads backups operations logs config', '--confirm', 'docker-backup.sh']) expect(restoreScript, marker, `Docker-Restore ${marker}`);
|
||
|
||
for (const marker of ['.env', 'runtime/', '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.37.0 erfolgreich', 'MODULE_DEPENDENCY_CYCLE', 'ROUTE_POLICY_REQUIRED']) expect(architectureGate, marker, `Architektur-Gate ${marker}`);
|
||
for (const marker of ['Theme-Manager-Gate 1.37.0 erfolgreich', 'THEME_VALUE_INVALID', 'theme_profiles', 'user_theme_preferences']) expect(themeGate, marker, `Theme-Gate ${marker}`);
|
||
for (const marker of ['Security-Foundation-Gate 1.37.0 erfolgreich', 'SECRET_VALUE_INVALID', 'requestContextMiddleware']) expect(securityGate, marker, `Security-Gate ${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']) 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',
|
||
]) 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) ||
|
||
/^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.37.0 fehlgeschlagen (${failures.length}):`);
|
||
failures.forEach(item => console.error(`- ${item}`));
|
||
process.exit(1);
|
||
}
|
||
console.log('Deployment-Gate 1.37.0 erfolgreich: native Theme- und Security-Module, verschlüsselte Secrets, CSP, Request-Telemetrie, Zero-Edit-Installer, CI und Release-Workflow geprüft.');
|