94 lines
3.0 KiB
JavaScript
94 lines
3.0 KiB
JavaScript
|
|
#!/usr/bin/env node
|
||
|
|
// ═══════════════════════════════════════════════════════════════════════════
|
||
|
|
// Runtime Trace v2 — Rikare blockeringsinformation
|
||
|
|
// ═══════════════════════════════════════════════════════════════════════════
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Runtime Trace v2
|
||
|
|
*
|
||
|
|
* Varje blockering innehåller:
|
||
|
|
* - Vilken policy som stoppade
|
||
|
|
* - Vilken evidens som användes
|
||
|
|
* - Vilken riskklass som utlöstes
|
||
|
|
* - Vilken minsta åtgärd som krävs för att gå vidare
|
||
|
|
*/
|
||
|
|
|
||
|
|
class RuntimeTraceV2 {
|
||
|
|
constructor() {
|
||
|
|
this.nodes = [];
|
||
|
|
this.startTime = Date.now();
|
||
|
|
}
|
||
|
|
|
||
|
|
addNode(phase, data = {}) {
|
||
|
|
const node = {
|
||
|
|
id: `node-${this.nodes.length}`,
|
||
|
|
phase,
|
||
|
|
timestamp: Date.now() - this.startTime,
|
||
|
|
status: 'running',
|
||
|
|
data,
|
||
|
|
result: null
|
||
|
|
};
|
||
|
|
this.nodes.push(node);
|
||
|
|
return node;
|
||
|
|
}
|
||
|
|
|
||
|
|
completeNode(nodeId, result) {
|
||
|
|
const node = this.nodes.find(n => n.id === nodeId);
|
||
|
|
if (node) {
|
||
|
|
node.status = 'completed';
|
||
|
|
node.result = result;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
blockNode(nodeId, reason, policyInfo = {}) {
|
||
|
|
const node = this.nodes.find(n => n.id === nodeId);
|
||
|
|
if (node) {
|
||
|
|
node.status = 'blocked';
|
||
|
|
node.reason = reason;
|
||
|
|
node.policyInfo = {
|
||
|
|
policyId: policyInfo.policyId || 'UNKNOWN',
|
||
|
|
policyName: policyInfo.policyName || 'Unknown Policy',
|
||
|
|
evidence: policyInfo.evidence || {},
|
||
|
|
riskClass: policyInfo.riskClass || 'CRITICAL',
|
||
|
|
requiredAction: policyInfo.requiredAction || 'Kontakta EOS Team för manuell granskning',
|
||
|
|
...policyInfo
|
||
|
|
};
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
toText() {
|
||
|
|
let output = `Task\n`;
|
||
|
|
output += `Duration: ${Date.now() - this.startTime}ms\n`;
|
||
|
|
output += `Nodes: ${this.nodes.length}\n\n`;
|
||
|
|
|
||
|
|
for (const node of this.nodes) {
|
||
|
|
const icon = node.status === 'blocked' ? '❌' : node.status === 'completed' ? '✅' : '⏳';
|
||
|
|
output += `${icon} ${node.phase} (${node.timestamp}ms)\n`;
|
||
|
|
|
||
|
|
if (node.status === 'blocked' && node.policyInfo) {
|
||
|
|
output += ` Blocked: ${node.reason}\n`;
|
||
|
|
output += ` Policy: ${node.policyInfo.policyId} — ${node.policyInfo.policyName}\n`;
|
||
|
|
output += ` Risk Class: ${node.policyInfo.riskClass}\n`;
|
||
|
|
output += ` Evidence: ${JSON.stringify(node.policyInfo.evidence)}\n`;
|
||
|
|
output += ` Required Action: ${node.policyInfo.requiredAction}\n`;
|
||
|
|
} else if (node.result) {
|
||
|
|
output += ` Result: ${JSON.stringify(node.result)}\n`;
|
||
|
|
}
|
||
|
|
|
||
|
|
output += ` Data: ${JSON.stringify(node.data)}\n\n`;
|
||
|
|
}
|
||
|
|
|
||
|
|
return output;
|
||
|
|
}
|
||
|
|
|
||
|
|
toJSON() {
|
||
|
|
return {
|
||
|
|
duration: Date.now() - this.startTime,
|
||
|
|
nodes: this.nodes,
|
||
|
|
blocked: this.nodes.some(n => n.status === 'blocked')
|
||
|
|
};
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
export { RuntimeTraceV2 };
|