Files
vendoo/tools/verify-platform-architecture-1.37.0.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

53 lines
4.5 KiB
JavaScript

import { readFileSync } from 'fs';
import { dirname, join, resolve } from 'path';
import { fileURLToPath } from 'url';
import { ModuleRegistry } from '../app/kernel/module-registry.mjs';
import { PolicyEngine } from '../app/kernel/policy-engine.mjs';
import { RouteRegistry } from '../app/kernel/route-registry.mjs';
import { EventBus } from '../app/kernel/event-bus.mjs';
import { loadBuiltInModules } from '../app/modules/catalog.mjs';
const root = resolve(dirname(fileURLToPath(import.meta.url)), '..');
const failures = [];
const assert = (condition, message) => { if (!condition) failures.push(message); };
const expectThrow = async (fn, code, message) => { try { await fn(); failures.push(message); } catch (error) { if (error.code !== code) failures.push(`${message} (${error.code || error.message})`); } };
const pkg = JSON.parse(readFileSync(join(root, 'package.json'), 'utf8'));
assert(pkg.version === '1.37.0', `package.json ist ${pkg.version}`);
const modules = loadBuiltInModules();
assert(modules.length === 12, `Erwartet 12 Module, erhalten ${modules.length}`);
const themeModule = modules.find(item => item.manifest.id === 'vendoo.themes');
assert(themeModule?.manifest.status === 'native', 'Theme-Modul ist nicht nativ');
const securityModule = modules.find(item => item.manifest.id === 'vendoo.security');
assert(securityModule?.manifest.status === 'native', 'Security-Modul ist nicht nativ');
assert(modules.filter(item => item.manifest.status === 'legacy-bridge').length === 10, 'Es müssen 10 Legacy-Bridges verbleiben');
const registry = new ModuleRegistry();
for (const module of modules) registry.register(module);
assert(registry.snapshot().length === 12, 'Modulregistrierung unvollständig');
const cycle = new ModuleRegistry();
cycle.register({ manifest: { schemaVersion:1,id:'vendoo.a',name:'A',version:'1.0.0',type:'feature',status:'native',requires:['vendoo.b'],permissions:[],provides:['a.ready'],consumes:[],owns:['a.state'] } });
cycle.register({ manifest: { schemaVersion:1,id:'vendoo.b',name:'B',version:'1.0.0',type:'feature',status:'native',requires:['vendoo.a'],permissions:[],provides:['b.ready'],consumes:[],owns:['b.state'] } });
await expectThrow(() => cycle.startAll({}), 'MODULE_DEPENDENCY_CYCLE', 'Zyklus wurde nicht blockiert');
const policies = new PolicyEngine();
policies.register('themes.use', ({ user }) => Boolean(user));
policies.register('security.secrets.manage', ({ user }) => Boolean(user?.admin));
const routes = new RouteRegistry({ policyEngine: policies });
const fake = { get(_path, handler) { this.handler = handler; } };
await expectThrow(() => routes.register(fake, { id:'themes.no-policy',method:'GET',path:'/x',owner:'vendoo.themes',handler(){} }), 'ROUTE_POLICY_REQUIRED', 'Route ohne Policy wurde akzeptiert');
routes.register(fake, { id:'themes.read',method:'GET',path:'/x',owner:'vendoo.themes',policy:'themes.use',csrf:false,handler(_req,res){res.json({ok:true});} });
let status = 0; await fake.handler({ user:null, requestId:'test' }, { headersSent:false,status(code){status=code;return this;},json(){} },()=>{});
assert(status === 403, `Deny-by-default ergab ${status}`);
const inputRoutes = new RouteRegistry({ policyEngine: policies });
const fakePut = { put(_path, handler) { this.handler = handler; } };
inputRoutes.register(fakePut, { id:'security.secret.write', method:'PUT', path:'/secret', owner:'vendoo.security', policy:'security.secrets.manage', input: body => { if (!body?.value) { const error=new Error('invalid'); error.status=400; throw error; } return Object.freeze({ value:String(body.value) }); }, handler(req,res){res.json(req.validatedBody);} });
const events = new EventBus(); let count = 0; events.on('themes.changed', () => count++, { owner:'vendoo.themes' }); await events.emit('themes.changed');
assert(count === 1 && events.removeOwner('vendoo.themes') === 1, 'Event-Bus Owner-Cleanup fehlerhaft');
const kernelSource = readFileSync(join(root, 'app/kernel/platform-kernel.mjs'), 'utf8');
for (const marker of ["policies.register('themes.use'", "policies.register('themes.manage'", "policies.register('security.secrets.manage'", "features.define('themes.manager'", "features.define('security.encrypted-secret-store'"]) assert(kernelSource.includes(marker), `Kernelvertrag fehlt: ${marker}`);
if (failures.length) { console.error(`Platform-Architecture-Gate 1.37.0 fehlgeschlagen (${failures.length}):`); failures.forEach(item => console.error(`- ${item}`)); process.exit(1); }
console.log('Platform-Architecture-Gate 1.37.0 erfolgreich: 12 Module, 2 native Module, 10 Legacy-Bridges, Policies, Routenverträge und Event-Grenzen geprüft.');