05ed037fe8
- 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!
166 lines
4.3 KiB
JavaScript
166 lines
4.3 KiB
JavaScript
#!/usr/bin/env node
|
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
// Infrastructure Knowledge Graph
|
|
// Kopplar affärskapacitet till underliggande infrastruktur
|
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
|
|
/**
|
|
* Exempel:
|
|
*
|
|
* Capability: Mission Management
|
|
* ↓
|
|
* Service: Mission Service
|
|
* ↓
|
|
* ALB → EC2 → IAM Role → Security Group → Subnet → VPC
|
|
* ↓
|
|
* RDS → Secrets → CloudWatch → Backup
|
|
*/
|
|
|
|
class InfrastructureKnowledgeGraph {
|
|
constructor() {
|
|
this.nodes = new Map();
|
|
this.edges = new Map();
|
|
}
|
|
|
|
addNode(id, type, properties = {}) {
|
|
this.nodes.set(id, {
|
|
id,
|
|
type,
|
|
properties,
|
|
discoveredAt: new Date().toISOString(),
|
|
source: properties.source || 'unknown'
|
|
});
|
|
return this;
|
|
}
|
|
|
|
addEdge(from, to, type) {
|
|
if (!this.edges.has(from)) {
|
|
this.edges.set(from, []);
|
|
}
|
|
this.edges.get(from).push({ to, type });
|
|
return this;
|
|
}
|
|
|
|
getDependencies(nodeId) {
|
|
const deps = [];
|
|
const visited = new Set();
|
|
|
|
const visit = (id) => {
|
|
if (visited.has(id)) return;
|
|
visited.add(id);
|
|
|
|
const edges = this.edges.get(id) || [];
|
|
for (const edge of edges) {
|
|
deps.push(edge.to);
|
|
visit(edge.to);
|
|
}
|
|
};
|
|
|
|
visit(nodeId);
|
|
return deps;
|
|
}
|
|
|
|
toJSON() {
|
|
return {
|
|
nodes: Array.from(this.nodes.values()),
|
|
edges: Array.from(this.edges.entries()).flatMap(([from, edges]) =>
|
|
edges.map(e => ({ from, to: e.to, type: e.type }))
|
|
),
|
|
metadata: {
|
|
generatedAt: new Date().toISOString(),
|
|
version: '1.0'
|
|
}
|
|
};
|
|
}
|
|
}
|
|
|
|
// Exempel: aamos-ledger
|
|
function buildLedgerGraph() {
|
|
const graph = new InfrastructureKnowledgeGraph();
|
|
|
|
// Capability
|
|
graph.addNode('capability-ledger', 'Capability', {
|
|
name: 'Accounting / Bokföring',
|
|
description: 'Dubbel bokföring med BAS-konton'
|
|
});
|
|
|
|
// Service
|
|
graph.addNode('service-ledger', 'Service', {
|
|
name: 'aamos-ledger',
|
|
port: 3250,
|
|
status: 'inactive' // STOP-001
|
|
});
|
|
|
|
// Compute
|
|
graph.addNode('ec2-ledger', 'EC2', {
|
|
instanceId: 'i-09b2204a52c2f33c9',
|
|
type: 'r8g.4xlarge',
|
|
status: 'running'
|
|
});
|
|
|
|
// Network
|
|
graph.addNode('sg-ledger', 'SecurityGroup', {
|
|
name: 'aamos-ledger-sg',
|
|
rules: ['3250/tcp']
|
|
});
|
|
|
|
graph.addNode('subnet-ledger', 'Subnet', {
|
|
cidr: '10.0.1.0/24'
|
|
});
|
|
|
|
graph.addNode('vpc-aamos', 'VPC', {
|
|
id: 'vpc-0e880ea5814b9f1be',
|
|
cidr: '10.0.0.0/16'
|
|
});
|
|
|
|
// Database
|
|
graph.addNode('rds-ledger', 'RDS', {
|
|
endpoint: 'platform-identity-core.cvi0qcksmsfj.eu-north-1.rds.amazonaws.com',
|
|
engine: 'postgresql'
|
|
});
|
|
|
|
// Cache
|
|
graph.addNode('redis-ledger', 'ElastiCache', {
|
|
status: 'unknown'
|
|
});
|
|
|
|
// Secrets
|
|
graph.addNode('secret-jwt', 'Secret', {
|
|
name: 'aamos-ledger/prod/jwt-secret',
|
|
rotation: false // STOP-013
|
|
});
|
|
|
|
graph.addNode('secret-db', 'Secret', {
|
|
name: 'platform/prod/ledger-db-url',
|
|
rotation: false // STOP-013
|
|
});
|
|
|
|
// Observability
|
|
graph.addNode('cw-ledger', 'CloudWatch', {
|
|
alarms: 0,
|
|
logs: 0
|
|
});
|
|
|
|
// Edges
|
|
graph.addEdge('capability-ledger', 'service-ledger', 'provides');
|
|
graph.addEdge('service-ledger', 'ec2-ledger', 'runs-on');
|
|
graph.addEdge('ec2-ledger', 'sg-ledger', 'secured-by');
|
|
graph.addEdge('ec2-ledger', 'subnet-ledger', 'in');
|
|
graph.addEdge('subnet-ledger', 'vpc-aamos', 'in');
|
|
graph.addEdge('service-ledger', 'rds-ledger', 'uses');
|
|
graph.addEdge('service-ledger', 'redis-ledger', 'uses');
|
|
graph.addEdge('service-ledger', 'secret-jwt', 'authenticates-with');
|
|
graph.addEdge('service-ledger', 'secret-db', 'connects-with');
|
|
graph.addEdge('service-ledger', 'cw-ledger', 'monitored-by');
|
|
|
|
return graph;
|
|
}
|
|
|
|
// CLI
|
|
if (process.argv[1] === new URL(import.meta.url).pathname) {
|
|
const graph = buildLedgerGraph();
|
|
console.log(JSON.stringify(graph.toJSON(), null, 2));
|
|
}
|
|
|
|
export { InfrastructureKnowledgeGraph, buildLedgerGraph };
|