Manifestbasierter Production-Updater 3.3, Modulnavigation, optionales Produktbild Studio, Listing-Studio-Aktionsleiste sowie plattformübergreifende Windows-/Linux-Release-Gates.
157 lines
14 KiB
JavaScript
157 lines
14 KiB
JavaScript
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(),
|
|
};
|
|
},
|
|
});
|
|
}
|