import { EventBus } from './event-bus.mjs'; import { FeatureFlagRegistry } from './feature-flags.mjs'; import { LifecycleManager } from './lifecycle.mjs'; import { ModuleRegistry } from './module-registry.mjs'; import { PolicyEngine } from './policy-engine.mjs'; import { RouteRegistry } from './route-registry.mjs'; import { loadBuiltInModules } from '../modules/catalog.mjs'; import { ModuleStateStore } from '../core/modules/module-state-store.mjs'; import { ModulePackageStore } from '../core/modules/module-package-store.mjs'; import { createExternalLifecycle, PROTECTED_MODULE_IDS } from '../modules/module-manager/service.mjs'; import { MODULES_DIR, MODULE_STATE_PATH } from '../../lib/runtime-paths.mjs'; export function createPlatformKernel({ version, hasPermission, moduleTrustKeys = {} }) { const events = new EventBus(); const features = new FeatureFlagRegistry(); const modules = new ModuleRegistry(); const moduleStateStore = new ModuleStateStore(MODULE_STATE_PATH); const modulePackageStore = new ModulePackageStore(MODULES_DIR, { trustKeys: moduleTrustKeys }); const policies = new PolicyEngine(); const routes = new RouteRegistry({ policyEngine: policies, moduleRegistry: modules }); const lifecycle = new LifecycleManager(); policies.register('platform.authenticated', ({ user }) => Boolean(user), { description: 'Erfordert eine gültige Vendoo-Sitzung.', }); policies.register('platform.security-admin', ({ user }) => Boolean(user && hasPermission(user.role, 'security.manage')), { description: 'Erfordert die Berechtigung security.manage.', }); policies.register('security.secrets.manage', ({ user }) => Boolean(user && hasPermission(user.role, 'security.manage')), { owner: 'vendoo.security', description: 'Erfordert security.manage für verschlüsselte Zugangsdaten.', }); policies.register('auth.public', () => true, { owner: 'vendoo.auth', description: 'Öffentliche Authentifizierungsroute mit eigener Eingabe- und Rate-Limit-Prüfung.' }); policies.register('auth.authenticated', ({ user }) => Boolean(user), { owner: 'vendoo.auth', description: 'Erfordert eine gültige Vendoo-Identität.' }); policies.register('users.self', ({ user }) => Boolean(user), { owner: 'vendoo.users', description: 'Erlaubt Zugriff auf das eigene Benutzerprofil.' }); policies.register('users.manage', ({ user }) => Boolean(user && hasPermission(user.role, 'users.manage')), { owner: 'vendoo.users', description: 'Erfordert users.manage.' }); policies.register('sessions.self', ({ user }) => Boolean(user), { owner: 'vendoo.sessions', description: 'Erlaubt Zugriff auf eigene Sitzungen.' }); policies.register('sessions.manage', ({ user }) => Boolean(user && hasPermission(user.role, 'sessions.manage')), { owner: 'vendoo.sessions', description: 'Erfordert sessions.manage.' }); policies.register('settings.read', ({ user }) => Boolean(user), { owner: 'vendoo.settings', description: 'Erfordert eine gültige Sitzung zum Lesen der Anwendungseinstellungen.' }); policies.register('settings.manage', ({ user }) => Boolean(user && hasPermission(user.role, 'settings.manage')), { owner: 'vendoo.settings', description: 'Erfordert settings.manage.' }); policies.register('listings.view', ({ user }) => Boolean(user && hasPermission(user.role, 'listings.view')), { owner: 'vendoo.listings', description: 'Erfordert listings.view.' }); policies.register('listings.edit', ({ user }) => Boolean(user && hasPermission(user.role, 'listings.edit')), { owner: 'vendoo.listings', description: 'Erfordert listings.edit.' }); policies.register('listings.delete', ({ user }) => Boolean(user && hasPermission(user.role, 'listings.delete')), { owner: 'vendoo.listings', description: 'Erfordert listings.delete.' }); policies.register('listings.permanent-delete', ({ user }) => Boolean(user && hasPermission(user.role, 'listings.permanent_delete')), { owner: 'vendoo.listings', description: 'Erfordert listings.permanent_delete.' }); policies.register('inventory.view', ({ user }) => Boolean(user && hasPermission(user.role, 'listings.view')), { owner: 'vendoo.inventory', description: 'Erfordert listings.view für Lagerübersichten.' }); policies.register('inventory.manage', ({ user }) => Boolean(user && hasPermission(user.role, 'inventory.edit')), { owner: 'vendoo.inventory', description: 'Erfordert inventory.edit.' }); policies.register('media.view', ({ user }) => Boolean(user && hasPermission(user.role, 'media.view')), { owner: 'vendoo.media', description: 'Erfordert media.view.' }); policies.register('media.edit', ({ user }) => Boolean(user && hasPermission(user.role, 'media.edit')), { owner: 'vendoo.media', description: 'Erfordert media.edit.' }); policies.register('media.delete', ({ user }) => Boolean(user && hasPermission(user.role, 'media.delete')), { owner: 'vendoo.media', description: 'Erfordert media.delete.' }); policies.register('themes.use', ({ user }) => Boolean(user), { owner: 'vendoo.themes', description: 'Erfordert eine gültige Sitzung für persönliche Darstellungseinstellungen.', }); policies.register('themes.manage', ({ user }) => Boolean(user && hasPermission(user.role, 'settings.manage')), { owner: 'vendoo.themes', description: 'Erfordert settings.manage für systemweite und eigene Theme-Profile.', }); policies.register('modules.manage', ({ user }) => Boolean(user && hasPermission(user.role, 'modules.manage')), { owner: 'vendoo.module-manager', description: 'Erfordert modules.manage für Installation, Aktivierung, Export und Entfernung von Modulen.', }); policies.register('publishing.view', ({ user }) => Boolean(user && hasPermission(user.role, 'publishing.view')), { owner: 'vendoo.publishing', description: 'Erfordert publishing.view.' }); policies.register('publishing.execute', ({ user }) => Boolean(user && hasPermission(user.role, 'publishing.execute')), { owner: 'vendoo.publishing', description: 'Erfordert publishing.execute.' }); policies.register('publishing.manage', ({ user }) => Boolean(user && hasPermission(user.role, 'publishing.manage')), { owner: 'vendoo.publishing', description: 'Erfordert publishing.manage.' }); policies.register('ai.execute', ({ user }) => Boolean(user && hasPermission(user.role, 'generation.execute')), { owner: 'vendoo.ai', description: 'Erfordert generation.execute.' }); policies.register('flux.execute', ({ user }) => Boolean(user && hasPermission(user.role, 'generation.execute')), { owner: 'vendoo.flux-studio', description: 'Erfordert generation.execute.' }); policies.register('quality.view', ({ user }) => Boolean(user && hasPermission(user.role, 'listings.view')), { owner: 'vendoo.quality', description: 'Erfordert listings.view.' }); policies.register('quality.execute', ({ user }) => Boolean(user && hasPermission(user.role, 'quality.execute')), { owner: 'vendoo.quality', description: 'Erfordert quality.execute.' }); policies.register('updates.manage', ({ user }) => Boolean(user && hasPermission(user.role, 'updates.manage')), { owner: 'vendoo.deployments', description: 'Erfordert updates.manage für Coolify-Deployment und Web-Updates.' }); features.define('platform.module-kernel', { defaultValue: true, description: 'Aktiviert den modularen Plattformkernel.' }); features.define('platform.route-contracts', { defaultValue: true, description: 'Aktiviert registrierte Routenverträge.' }); features.define('security.encrypted-secret-store', { defaultValue: true, owner: 'vendoo.security', description: 'Aktiviert AES-256-GCM-verschlüsselte Zugangsdaten außerhalb der Runtime-Konfiguration.' }); features.define('security.request-telemetry', { defaultValue: true, owner: 'vendoo.security', description: 'Aktiviert Request-/Correlation-IDs und strukturierte Telemetrie.' }); features.define('security.strict-script-csp', { defaultValue: true, owner: 'vendoo.security', description: 'Blockiert Inline-Skripte und Inline-Eventhandler per CSP.' }); features.define('identity.native-auth', { defaultValue: true, owner: 'vendoo.auth', description: 'Aktiviert native Setup-, Login- und Einladungsabläufe.' }); features.define('identity.native-users', { defaultValue: true, owner: 'vendoo.users', description: 'Aktiviert native Benutzer- und Rollenverwaltung.' }); features.define('identity.native-sessions', { defaultValue: true, owner: 'vendoo.sessions', description: 'Aktiviert eigentümergebundene Sitzungsverwaltung und Revocation.' }); features.define('settings.native-module', { defaultValue: true, owner: 'vendoo.settings', description: 'Aktiviert allowlist-basierte Anwendungs- und SMTP-Einstellungen.' }); features.define('catalog.native-listings', { defaultValue: true, owner: 'vendoo.listings', description: 'Aktiviert native Artikel-, Duplikat- und Papierkorbverträge.' }); features.define('catalog.native-inventory', { defaultValue: true, owner: 'vendoo.inventory', description: 'Aktiviert native Lagerort- und Bulk-Bestandsverträge.' }); features.define('catalog.native-media', { defaultValue: true, owner: 'vendoo.media', description: 'Aktiviert native Medienbibliothek und Referenzschutz.' }); features.define('themes.token-runtime', { defaultValue: true, owner: 'vendoo.themes', description: 'Aktiviert den versionierten Design-Token-Vertrag.' }); features.define('themes.manager', { defaultValue: true, owner: 'vendoo.themes', description: 'Aktiviert den sicheren Theme Manager mit Benutzerpräferenzen.' }); features.define('themes.accessibility-gate', { defaultValue: true, owner: 'vendoo.themes', description: 'Prüft Theme-Kontraste und sichere Tokenwerte.' }); features.define('extensions.isolated-host', { defaultValue: false, owner: 'vendoo.security', description: 'Reserviert für einen späteren isolierten Extension-Host.' }); features.define('modules.manager', { defaultValue: true, owner: 'vendoo.module-manager', description: 'Aktiviert den sicheren Modulmanager und den persistenten Modulstatus.' }); features.define('modules.package-format', { defaultValue: true, owner: 'vendoo.module-manager', description: 'Aktiviert validierte .vmod-Pakete mit SHA-256-Integrität und optionaler Ed25519-Signatur.' }); features.define('publishing.native-module', { defaultValue: true, owner: 'vendoo.publishing', description: 'Aktiviert native Publishing-Verträge.' }); features.define('ai.native-module', { defaultValue: true, owner: 'vendoo.ai', description: 'Aktiviert native AI-Verträge.' }); features.define('product-images.optional-module', { defaultValue: false, owner: 'vendoo.product-image-tools', description: 'Aktiviert optionale Ghost-Mannequin- und Flatlay-Produktbildvarianten.' }); features.define('flux.native-module', { defaultValue: true, owner: 'vendoo.flux-studio', description: 'Aktiviert native FLUX-Verträge.' }); features.define('quality.native-module', { defaultValue: true, owner: 'vendoo.quality', description: 'Aktiviert native Quality-Verträge.' }); features.define('deployments.coolify', { defaultValue: true, owner: 'vendoo.deployments', description: 'Aktiviert kontrollierte Coolify-Deployments ohne Docker-Socket.' }); features.define('updates.web-trigger', { defaultValue: true, owner: 'vendoo.deployments', description: 'Erlaubt Administratoren, einen geprüften Coolify-Deployment-Auftrag aus dem Update Center anzufordern.' }); const initialDisabledModules = new Set(String(process.env.VENDOO_INITIAL_DISABLED_MODULES || '') .split(',').map(value => value.trim()).filter(Boolean)); for (const module of loadBuiltInModules()) { const forcedEnabled = PROTECTED_MODULE_IDS.includes(module.manifest.id); const defaultEnabled = module.manifest.status !== 'disabled' && module.manifest.defaultEnabled !== false && !initialDisabledModules.has(module.manifest.id); const enabled = forcedEnabled || moduleStateStore.isEnabled(module.manifest.id, defaultEnabled); modules.register(module, { enabled }); } for (const installed of modulePackageStore.list()) { if (installed.invalid || modules.has(installed.id)) continue; try { const pkg = modulePackageStore.get(installed.id); const enabled = installed.activatable && moduleStateStore.isEnabled(installed.id, false); modules.register({ manifest: pkg.manifest, lifecycle: createExternalLifecycle(pkg), source: 'external' }, { enabled }); } catch { // Ungültige oder konfliktbehaftete Fremdmodule bleiben quarantänisiert und erscheinen im Modulmanager. } } lifecycle.register({ id: 'modules', order: 20, start: context => modules.startAll(context), stop: context => modules.stopAll(context), }); const context = Object.freeze({ version, events, features, policies, modules, moduleStateStore, modulePackageStore }); return Object.freeze({ version, events, features, lifecycle, modules, policies, routes, async start() { await lifecycle.start(context); await events.emit('platform.started', { version }, { owner: 'vendoo.system' }); }, async stop() { await events.emit('platform.stopping', { version }, { owner: 'vendoo.system' }); await lifecycle.stop(context); }, async health() { const moduleChecks = await modules.health(); return { ok: lifecycle.snapshot().state === 'running' && moduleChecks.every(check => check.ok), lifecycle: lifecycle.snapshot(), modules: moduleChecks, }; }, snapshot() { return { version, architecture: 'modular-monolith', lifecycle: lifecycle.snapshot(), modules: modules.snapshot(), features: features.list(), policies: policies.list(), routes: routes.list(), moduleState: moduleStateStore.snapshot(), }; }, }); }