Files
boc/EOS/capability-registry.mjs
T
Bernt 05ed037fe8 pilot.landvex.com: HTTPS + Full Stack Verified
- DNS: pilot.landvex.com -> 16.170.83.169
- TLS: Let's Encrypt certificate (expires 2026-09-30)
- Nginx: reverse proxy with SSL termination
- API: https://pilot.landvex.com/api/v1/missions
- UI: https://pilot.landvex.com/
- Upload: POST /api/v1/missions/import (multipart/form-data)

Verified:
 https://pilot.landvex.com/health
 https://pilot.landvex.com/version
 https://pilot.landvex.com/api/v1/missions (list)
 https://pilot.landvex.com/api/v1/missions/:id (get)
 POST /api/v1/missions/import (video upload)
 UI loads with title 'LandveX Intelligence Lab'

Next: Pilot 001 — Break the system!
2026-07-02 17:34:19 +00:00

308 lines
9.5 KiB
JavaScript

#!/usr/bin/env node
// ═══════════════════════════════════════════════════════════════════════════
// EOS Capability Registry — Resonera i verksamhetsförmågor, inte tekniska komponenter
// Erik-krav: "Då börjar ni resonera i verksamhetsförmågor snarare än tekniska komponenter"
// ═══════════════════════════════════════════════════════════════════════════
import { readFileSync, writeFileSync, existsSync } from 'fs';
const REGISTRY_PATH = '/home/bernt/.openclaw/workspace/EOS/capability-registry.json';
/**
* Capabilities för quiXzoom/LandveX
*/
const DEFAULT_CAPABILITIES = [
{
id: 'cap-mission-mgmt',
name: 'Mission Management',
description: 'Hantera uppdrag (missions) för Zoomers',
owner: 'Mission Team',
services: ['Mission Service'],
apis: ['/mission/create', '/mission/assign', '/mission/complete'],
database: 'missions',
tests: ['mission.integration.ts'],
dashboards: ['Mission KPI', 'Completion Rate'],
dependencies: ['cap-user-mgmt', 'cap-payment'],
budget: {
maxDirectDeps: 8,
maxExternalApis: 2,
maxDatabases: 1
}
},
{
id: 'cap-user-mgmt',
name: 'User Management',
description: 'Hantera Zoomers, kunder och identiteter',
owner: 'Identity Team',
services: ['Identity Service', 'Wallet Service'],
apis: ['/user/register', '/user/login', '/user/verify'],
database: 'users',
tests: ['user.integration.ts', 'identity.unit.ts'],
dashboards: ['User Growth', 'Verification Rate'],
dependencies: ['cap-payment'],
budget: {
maxDirectDeps: 6,
maxExternalApis: 2,
maxDatabases: 1
}
},
{
id: 'cap-payment',
name: 'Payment Processing',
description: 'Hantera betalningar via Stripe Connect',
owner: 'Finance Team',
services: ['Payment Service', 'Stripe Adapter'],
apis: ['/payment/create', '/payment/webhook', '/payout/schedule'],
database: 'transactions',
tests: ['payment.integration.ts'],
dashboards: ['Revenue', 'Payout Status'],
dependencies: [],
budget: {
maxDirectDeps: 4,
maxExternalApis: 1,
maxDatabases: 1
}
},
{
id: 'cap-content',
name: 'Content Management',
description: 'Hantera bilder, video och dokument',
owner: 'Content Team',
services: ['Media Service', 'Storage Adapter'],
apis: ['/media/upload', '/media/retrieve', '/media/delete'],
database: 'media_metadata',
tests: ['media.integration.ts'],
dashboards: ['Storage Usage', 'Upload Success Rate'],
dependencies: [],
budget: {
maxDirectDeps: 5,
maxExternalApis: 1,
maxDatabases: 1
}
},
{
id: 'cap-analytics',
name: 'Analytics & Reporting',
description: 'Samla och analysera data',
owner: 'Data Team',
services: ['Analytics Service', 'Report Engine'],
apis: ['/analytics/event', '/report/generate'],
database: 'analytics',
tests: ['analytics.unit.ts'],
dashboards: ['System Health', 'Business Metrics'],
dependencies: ['cap-mission-mgmt', 'cap-user-mgmt'],
budget: {
maxDirectDeps: 6,
maxExternalApis: 2,
maxDatabases: 1
}
}
];
class CapabilityRegistry {
constructor() {
this.capabilities = this.loadCapabilities();
}
loadCapabilities() {
if (existsSync(REGISTRY_PATH)) {
return JSON.parse(readFileSync(REGISTRY_PATH, 'utf8'));
}
return DEFAULT_CAPABILITIES;
}
saveCapabilities() {
writeFileSync(REGISTRY_PATH, JSON.stringify(this.capabilities, null, 2));
}
/**
* Hitta capability från vilken som helst referens
*/
resolve(reference) {
// Sök på ID
let cap = this.capabilities.find(c => c.id === reference);
if (cap) return cap;
// Sök på service
cap = this.capabilities.find(c => c.services.includes(reference));
if (cap) return cap;
// Sök på API
cap = this.capabilities.find(c => c.apis.includes(reference));
if (cap) return cap;
// Sök på databas
cap = this.capabilities.find(c => c.database === reference);
if (cap) return cap;
return null;
}
/**
* Kontrollera om en ändring bryter mot capability-struktur
*/
validateChange(change) {
const cap = this.resolve(change.capability);
if (!cap) {
return {
valid: false,
reason: `Ingen capability hittad för: ${change.capability}`
};
}
const issues = [];
// Kontrollera beroenden
if (change.newDependencies) {
const currentDeps = cap.dependencies.length;
const newDeps = change.newDependencies.length;
if (currentDeps + newDeps > cap.budget.maxDirectDeps) {
issues.push(`För många beroenden: ${currentDeps + newDeps}/${cap.budget.maxDirectDeps}`);
}
}
// Kontrollera externa API:er
if (change.newExternalApis) {
const currentApis = cap.apis.filter(a => a.includes('stripe') || a.includes('external')).length;
const newApis = change.newExternalApis.length;
if (currentApis + newApis > cap.budget.maxExternalApis) {
issues.push(`För många externa API:er: ${currentApis + newApis}/${cap.budget.maxExternalApis}`);
}
}
// Kontrollera databaser
if (change.newDatabase) {
if (cap.database && change.newDatabase !== cap.database) {
issues.push(`Flera databaser: ${cap.database}, ${change.newDatabase} (max: ${cap.budget.maxDatabases})`);
}
}
return {
valid: issues.length === 0,
capability: cap,
issues,
budget: cap.budget
};
}
/**
* Visa capability-karta
*/
showMap() {
console.log('🗺️ CAPABILITY MAP\n');
for (const cap of this.capabilities) {
console.log(`📦 ${cap.name} (${cap.id})`);
console.log(` ${cap.description}`);
console.log(` Ägare: ${cap.owner}`);
console.log();
console.log(' 🔗 Services:');
for (const service of cap.services) {
console.log(`${service}`);
}
console.log(' 📡 APIs:');
for (const api of cap.apis) {
console.log(`${api}`);
}
console.log(` 🗄️ Database: ${cap.database}`);
console.log(' 🧪 Tests:');
for (const test of cap.tests) {
console.log(`${test}`);
}
console.log(' 📊 Dashboards:');
for (const dash of cap.dashboards) {
console.log(`${dash}`);
}
if (cap.dependencies.length > 0) {
console.log(' ⬇️ Dependencies:');
for (const dep of cap.dependencies) {
const depCap = this.resolve(dep);
console.log(`${depCap?.name || dep}`);
}
}
console.log(' 💰 Budget:');
console.log(` Max direkta beroenden: ${cap.budget.maxDirectDeps}`);
console.log(` Max externa API:er: ${cap.budget.maxExternalApis}`);
console.log(` Max databaser: ${cap.budget.maxDatabases}`);
console.log();
}
}
/**
* Visa beroendegraf
*/
showDependencyGraph() {
console.log('📊 DEPENDENCY GRAPH\n');
for (const cap of this.capabilities) {
const deps = cap.dependencies.map(d => {
const depCap = this.resolve(d);
return depCap?.name || d;
});
const depCount = deps.length;
const budgetStatus = depCount > cap.budget.maxDirectDeps ? '🔴' :
depCount > cap.budget.maxDirectDeps * 0.8 ? '⚠️' : '✅';
console.log(`${depCount}/${cap.budget.maxDirectDeps} ${budgetStatus} ${cap.name}`);
if (deps.length > 0) {
for (const dep of deps) {
console.log(`${dep}`);
}
}
console.log();
}
}
}
// ── Main ──────────────────────────────────────────────────────────────────
const registry = new CapabilityRegistry();
const command = process.argv[2] || '--map';
if (command === '--map') {
registry.showMap();
} else if (command === '--deps') {
registry.showDependencyGraph();
} else if (command === '--validate') {
const change = {
capability: process.argv[3] || 'cap-mission-mgmt',
newDependencies: process.argv[4]?.split(',') || [],
newExternalApis: process.argv[5]?.split(',') || [],
newDatabase: process.argv[6] || null
};
const result = registry.validateChange(change);
console.log(`🔍 Validerar ändring för: ${change.capability}\n`);
if (result.valid) {
console.log('✅ Ändringen bryter inte mot capability-strukturen\n');
} else {
console.log('❌ Ändringen bryter mot capability-strukturen\n');
for (const issue of result.issues) {
console.log(`${issue}`);
}
console.log();
console.log('💰 Budget:');
console.log(` Max direkta beroenden: ${result.budget.maxDirectDeps}`);
console.log(` Max externa API:er: ${result.budget.maxExternalApis}`);
console.log(` Max databaser: ${result.budget.maxDatabases}`);
}
} else {
console.log('Användning:');
console.log(' node capability-registry.mjs --map # Visa capability-karta');
console.log(' node capability-registry.mjs --deps # Visa beroendegraf');
console.log(' node capability-registry.mjs --validate <cap> [deps] [apis] [db] # Validera ändring');
}