aura-security 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +446 -0
- package/deploy/AWS-DEPLOYMENT.md +358 -0
- package/deploy/terraform/main.tf +362 -0
- package/deploy/terraform/terraform.tfvars.example +6 -0
- package/dist/agents/base.d.ts +44 -0
- package/dist/agents/base.js +96 -0
- package/dist/agents/index.d.ts +14 -0
- package/dist/agents/index.js +17 -0
- package/dist/agents/policy/evaluator.d.ts +15 -0
- package/dist/agents/policy/evaluator.js +183 -0
- package/dist/agents/policy/index.d.ts +12 -0
- package/dist/agents/policy/index.js +15 -0
- package/dist/agents/policy/validator.d.ts +15 -0
- package/dist/agents/policy/validator.js +182 -0
- package/dist/agents/scanners/gitleaks.d.ts +14 -0
- package/dist/agents/scanners/gitleaks.js +155 -0
- package/dist/agents/scanners/grype.d.ts +14 -0
- package/dist/agents/scanners/grype.js +109 -0
- package/dist/agents/scanners/index.d.ts +15 -0
- package/dist/agents/scanners/index.js +27 -0
- package/dist/agents/scanners/npm-audit.d.ts +13 -0
- package/dist/agents/scanners/npm-audit.js +129 -0
- package/dist/agents/scanners/semgrep.d.ts +14 -0
- package/dist/agents/scanners/semgrep.js +131 -0
- package/dist/agents/scanners/trivy.d.ts +14 -0
- package/dist/agents/scanners/trivy.js +122 -0
- package/dist/agents/types.d.ts +137 -0
- package/dist/agents/types.js +91 -0
- package/dist/auditor/index.d.ts +3 -0
- package/dist/auditor/index.js +2 -0
- package/dist/auditor/pipeline.d.ts +19 -0
- package/dist/auditor/pipeline.js +240 -0
- package/dist/auditor/validator.d.ts +17 -0
- package/dist/auditor/validator.js +58 -0
- package/dist/aura/client.d.ts +29 -0
- package/dist/aura/client.js +125 -0
- package/dist/aura/index.d.ts +4 -0
- package/dist/aura/index.js +2 -0
- package/dist/aura/server.d.ts +45 -0
- package/dist/aura/server.js +343 -0
- package/dist/cli.d.ts +17 -0
- package/dist/cli.js +1433 -0
- package/dist/client/index.d.ts +41 -0
- package/dist/client/index.js +170 -0
- package/dist/compliance/index.d.ts +40 -0
- package/dist/compliance/index.js +292 -0
- package/dist/database/index.d.ts +77 -0
- package/dist/database/index.js +395 -0
- package/dist/index.d.ts +25 -0
- package/dist/index.js +762 -0
- package/dist/integrations/aura-scanner.d.ts +69 -0
- package/dist/integrations/aura-scanner.js +155 -0
- package/dist/integrations/aws-scanner.d.ts +63 -0
- package/dist/integrations/aws-scanner.js +624 -0
- package/dist/integrations/config.d.ts +69 -0
- package/dist/integrations/config.js +212 -0
- package/dist/integrations/github.d.ts +45 -0
- package/dist/integrations/github.js +201 -0
- package/dist/integrations/gitlab.d.ts +36 -0
- package/dist/integrations/gitlab.js +110 -0
- package/dist/integrations/index.d.ts +11 -0
- package/dist/integrations/index.js +11 -0
- package/dist/integrations/local-scanner.d.ts +146 -0
- package/dist/integrations/local-scanner.js +1654 -0
- package/dist/integrations/notifications.d.ts +99 -0
- package/dist/integrations/notifications.js +305 -0
- package/dist/integrations/scanners.d.ts +57 -0
- package/dist/integrations/scanners.js +217 -0
- package/dist/integrations/slop-scanner.d.ts +69 -0
- package/dist/integrations/slop-scanner.js +155 -0
- package/dist/integrations/webhook.d.ts +37 -0
- package/dist/integrations/webhook.js +256 -0
- package/dist/orchestrator/index.d.ts +72 -0
- package/dist/orchestrator/index.js +187 -0
- package/dist/output/index.d.ts +152 -0
- package/dist/output/index.js +399 -0
- package/dist/pipeline/index.d.ts +72 -0
- package/dist/pipeline/index.js +313 -0
- package/dist/sbom/index.d.ts +94 -0
- package/dist/sbom/index.js +298 -0
- package/dist/schemas/index.d.ts +2 -0
- package/dist/schemas/index.js +2 -0
- package/dist/schemas/input.schema.d.ts +87 -0
- package/dist/schemas/input.schema.js +44 -0
- package/dist/schemas/output.schema.d.ts +115 -0
- package/dist/schemas/output.schema.js +64 -0
- package/dist/serve-visualizer.d.ts +2 -0
- package/dist/serve-visualizer.js +78 -0
- package/dist/slop/client.d.ts +29 -0
- package/dist/slop/client.js +125 -0
- package/dist/slop/index.d.ts +4 -0
- package/dist/slop/index.js +2 -0
- package/dist/slop/server.d.ts +45 -0
- package/dist/slop/server.js +343 -0
- package/dist/types/events.d.ts +62 -0
- package/dist/types/events.js +2 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.js +1 -0
- package/dist/visualizer/index.d.ts +4 -0
- package/dist/visualizer/index.js +181 -0
- package/dist/websocket/index.d.ts +88 -0
- package/dist/websocket/index.js +195 -0
- package/dist/zones/index.d.ts +7 -0
- package/dist/zones/index.js +7 -0
- package/dist/zones/manager.d.ts +101 -0
- package/dist/zones/manager.js +304 -0
- package/dist/zones/types.d.ts +78 -0
- package/dist/zones/types.js +33 -0
- package/package.json +84 -0
- package/visualizer/app.js +0 -0
- package/visualizer/index-minimal.html +1771 -0
- package/visualizer/index.html +2933 -0
- package/visualizer/landing.html +1328 -0
- package/visualizer/styles.css +0 -0
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WebSocket Server for aurasecurity
|
|
3
|
+
*
|
|
4
|
+
* Provides real-time updates to connected clients:
|
|
5
|
+
* - Audit started/completed events
|
|
6
|
+
* - Finding notifications
|
|
7
|
+
* - Settings changes
|
|
8
|
+
* - Server status updates
|
|
9
|
+
*/
|
|
10
|
+
import { WebSocketServer, WebSocket } from 'ws';
|
|
11
|
+
export class AuditorWebSocket {
|
|
12
|
+
port;
|
|
13
|
+
wss = null;
|
|
14
|
+
clients = new Set();
|
|
15
|
+
pingInterval = null;
|
|
16
|
+
constructor(port = 3001) {
|
|
17
|
+
this.port = port;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Start the WebSocket server
|
|
21
|
+
*/
|
|
22
|
+
start() {
|
|
23
|
+
return new Promise((resolve, reject) => {
|
|
24
|
+
this.wss = new WebSocketServer({ port: this.port });
|
|
25
|
+
this.wss.on('connection', (ws, req) => {
|
|
26
|
+
console.log(`[WS] Client connected from ${req.socket.remoteAddress}`);
|
|
27
|
+
this.clients.add(ws);
|
|
28
|
+
// Send welcome message
|
|
29
|
+
this.sendTo(ws, {
|
|
30
|
+
type: 'status',
|
|
31
|
+
payload: { connected: true, clientCount: this.clients.size },
|
|
32
|
+
timestamp: new Date().toISOString()
|
|
33
|
+
});
|
|
34
|
+
ws.on('message', (data) => {
|
|
35
|
+
try {
|
|
36
|
+
const message = JSON.parse(data.toString());
|
|
37
|
+
this.handleMessage(ws, message);
|
|
38
|
+
}
|
|
39
|
+
catch (err) {
|
|
40
|
+
console.error('[WS] Invalid message:', err);
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
ws.on('close', () => {
|
|
44
|
+
console.log('[WS] Client disconnected');
|
|
45
|
+
this.clients.delete(ws);
|
|
46
|
+
});
|
|
47
|
+
ws.on('error', (err) => {
|
|
48
|
+
console.error('[WS] Client error:', err);
|
|
49
|
+
this.clients.delete(ws);
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
this.wss.on('error', (err) => {
|
|
53
|
+
console.error('[WS] Server error:', err);
|
|
54
|
+
reject(err);
|
|
55
|
+
});
|
|
56
|
+
this.wss.on('listening', () => {
|
|
57
|
+
console.log(`[WS] WebSocket server running on ws://127.0.0.1:${this.port}`);
|
|
58
|
+
// Start ping interval to keep connections alive
|
|
59
|
+
this.pingInterval = setInterval(() => {
|
|
60
|
+
this.broadcast({
|
|
61
|
+
type: 'ping',
|
|
62
|
+
payload: { time: Date.now() },
|
|
63
|
+
timestamp: new Date().toISOString()
|
|
64
|
+
});
|
|
65
|
+
}, 30000);
|
|
66
|
+
resolve();
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Stop the WebSocket server
|
|
72
|
+
*/
|
|
73
|
+
stop() {
|
|
74
|
+
return new Promise((resolve) => {
|
|
75
|
+
if (this.pingInterval) {
|
|
76
|
+
clearInterval(this.pingInterval);
|
|
77
|
+
this.pingInterval = null;
|
|
78
|
+
}
|
|
79
|
+
if (this.wss) {
|
|
80
|
+
// Close all client connections
|
|
81
|
+
for (const client of this.clients) {
|
|
82
|
+
client.close(1000, 'Server shutting down');
|
|
83
|
+
}
|
|
84
|
+
this.clients.clear();
|
|
85
|
+
this.wss.close(() => {
|
|
86
|
+
console.log('[WS] WebSocket server stopped');
|
|
87
|
+
resolve();
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
resolve();
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Handle incoming messages from clients
|
|
97
|
+
*/
|
|
98
|
+
handleMessage(ws, message) {
|
|
99
|
+
switch (message.type) {
|
|
100
|
+
case 'ping':
|
|
101
|
+
this.sendTo(ws, {
|
|
102
|
+
type: 'pong',
|
|
103
|
+
payload: { time: Date.now() },
|
|
104
|
+
timestamp: new Date().toISOString()
|
|
105
|
+
});
|
|
106
|
+
break;
|
|
107
|
+
case 'pong':
|
|
108
|
+
// Client responded to ping
|
|
109
|
+
break;
|
|
110
|
+
default:
|
|
111
|
+
console.log('[WS] Received:', message.type);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Send message to a specific client
|
|
116
|
+
*/
|
|
117
|
+
sendTo(ws, message) {
|
|
118
|
+
if (ws.readyState === WebSocket.OPEN) {
|
|
119
|
+
ws.send(JSON.stringify(message));
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Broadcast message to all connected clients
|
|
124
|
+
*/
|
|
125
|
+
broadcast(message) {
|
|
126
|
+
const data = JSON.stringify(message);
|
|
127
|
+
for (const client of this.clients) {
|
|
128
|
+
if (client.readyState === WebSocket.OPEN) {
|
|
129
|
+
client.send(data);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Notify clients that an audit has started
|
|
135
|
+
*/
|
|
136
|
+
notifyAuditStarted(payload) {
|
|
137
|
+
this.broadcast({
|
|
138
|
+
type: 'audit_started',
|
|
139
|
+
payload,
|
|
140
|
+
timestamp: new Date().toISOString()
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Notify clients that an audit has completed
|
|
145
|
+
*/
|
|
146
|
+
notifyAuditCompleted(payload) {
|
|
147
|
+
this.broadcast({
|
|
148
|
+
type: 'audit_completed',
|
|
149
|
+
payload,
|
|
150
|
+
timestamp: new Date().toISOString()
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Notify clients of a finding during an audit
|
|
155
|
+
*/
|
|
156
|
+
notifyFinding(payload) {
|
|
157
|
+
this.broadcast({
|
|
158
|
+
type: 'finding',
|
|
159
|
+
payload,
|
|
160
|
+
timestamp: new Date().toISOString()
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Notify clients that settings have changed
|
|
165
|
+
*/
|
|
166
|
+
notifySettingsChanged(section) {
|
|
167
|
+
this.broadcast({
|
|
168
|
+
type: 'settings_changed',
|
|
169
|
+
payload: { section },
|
|
170
|
+
timestamp: new Date().toISOString()
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Get the number of connected clients
|
|
175
|
+
*/
|
|
176
|
+
getClientCount() {
|
|
177
|
+
return this.clients.size;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
// Singleton instance
|
|
181
|
+
let wsServer = null;
|
|
182
|
+
export function getWebSocketServer(port) {
|
|
183
|
+
if (!wsServer) {
|
|
184
|
+
wsServer = new AuditorWebSocket(port);
|
|
185
|
+
}
|
|
186
|
+
return wsServer;
|
|
187
|
+
}
|
|
188
|
+
export function closeWebSocketServer() {
|
|
189
|
+
if (wsServer) {
|
|
190
|
+
const server = wsServer;
|
|
191
|
+
wsServer = null;
|
|
192
|
+
return server.stop();
|
|
193
|
+
}
|
|
194
|
+
return Promise.resolve();
|
|
195
|
+
}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Aura Protocol - Zone Manager
|
|
3
|
+
*
|
|
4
|
+
* Manages creation, execution, and lifecycle of zones.
|
|
5
|
+
* Zones are isolated execution environments that contain agents.
|
|
6
|
+
*/
|
|
7
|
+
import { EventEmitter } from 'events';
|
|
8
|
+
import { Zone, ZoneConfig, ZoneFinding, ZoneResult, ZoneStatus } from './types.js';
|
|
9
|
+
import { Agent } from '../agents/types.js';
|
|
10
|
+
export declare class ZoneManager extends EventEmitter {
|
|
11
|
+
private zones;
|
|
12
|
+
private agents;
|
|
13
|
+
constructor();
|
|
14
|
+
private initializeDefaultZones;
|
|
15
|
+
/**
|
|
16
|
+
* Create a new zone
|
|
17
|
+
*/
|
|
18
|
+
createZone(config: ZoneConfig): Zone;
|
|
19
|
+
/**
|
|
20
|
+
* Get a zone by ID
|
|
21
|
+
*/
|
|
22
|
+
getZone(zoneId: string): Zone | undefined;
|
|
23
|
+
/**
|
|
24
|
+
* Get all zones
|
|
25
|
+
*/
|
|
26
|
+
getAllZones(): Zone[];
|
|
27
|
+
/**
|
|
28
|
+
* Register an agent
|
|
29
|
+
*/
|
|
30
|
+
registerAgent(agent: Agent): void;
|
|
31
|
+
/**
|
|
32
|
+
* Get an agent by ID
|
|
33
|
+
*/
|
|
34
|
+
getAgent(agentId: string): Agent | undefined;
|
|
35
|
+
/**
|
|
36
|
+
* Get all agents
|
|
37
|
+
*/
|
|
38
|
+
getAllAgents(): Agent[];
|
|
39
|
+
/**
|
|
40
|
+
* Get agents for a specific zone
|
|
41
|
+
*/
|
|
42
|
+
getZoneAgents(zoneId: string): Agent[];
|
|
43
|
+
/**
|
|
44
|
+
* Assign an agent to a zone
|
|
45
|
+
*/
|
|
46
|
+
assignAgentToZone(agentId: string, zoneId: string): void;
|
|
47
|
+
/**
|
|
48
|
+
* Remove an agent from a zone
|
|
49
|
+
*/
|
|
50
|
+
removeAgentFromZone(agentId: string, zoneId: string): void;
|
|
51
|
+
/**
|
|
52
|
+
* Create a zone context for agent execution
|
|
53
|
+
*/
|
|
54
|
+
private createZoneContext;
|
|
55
|
+
/**
|
|
56
|
+
* Execute a single zone
|
|
57
|
+
*/
|
|
58
|
+
executeZone(zoneId: string, targetPath: string): Promise<ZoneResult>;
|
|
59
|
+
/**
|
|
60
|
+
* Execute multiple zones in parallel
|
|
61
|
+
*/
|
|
62
|
+
executeZonesParallel(zoneIds: string[], targetPath: string): Promise<Map<string, ZoneResult>>;
|
|
63
|
+
/**
|
|
64
|
+
* Execute all zones in parallel
|
|
65
|
+
*/
|
|
66
|
+
executeAllZones(targetPath: string): Promise<Map<string, ZoneResult>>;
|
|
67
|
+
/**
|
|
68
|
+
* Reset a zone to idle state
|
|
69
|
+
*/
|
|
70
|
+
resetZone(zoneId: string): void;
|
|
71
|
+
/**
|
|
72
|
+
* Get zone status
|
|
73
|
+
*/
|
|
74
|
+
getZoneStatus(zoneId: string): ZoneStatus | undefined;
|
|
75
|
+
/**
|
|
76
|
+
* Get all findings from all zones
|
|
77
|
+
*/
|
|
78
|
+
getAllFindings(): ZoneFinding[];
|
|
79
|
+
/**
|
|
80
|
+
* Export zone state for visualization
|
|
81
|
+
*/
|
|
82
|
+
exportState(): {
|
|
83
|
+
zones: Array<{
|
|
84
|
+
id: string;
|
|
85
|
+
name: string;
|
|
86
|
+
type: string;
|
|
87
|
+
color: string;
|
|
88
|
+
status: ZoneStatus;
|
|
89
|
+
agentCount: number;
|
|
90
|
+
findingCount: number;
|
|
91
|
+
}>;
|
|
92
|
+
agents: Array<{
|
|
93
|
+
id: string;
|
|
94
|
+
name: string;
|
|
95
|
+
role: string;
|
|
96
|
+
zoneId: string | null;
|
|
97
|
+
status: string;
|
|
98
|
+
}>;
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
export declare const zoneManager: ZoneManager;
|
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Aura Protocol - Zone Manager
|
|
3
|
+
*
|
|
4
|
+
* Manages creation, execution, and lifecycle of zones.
|
|
5
|
+
* Zones are isolated execution environments that contain agents.
|
|
6
|
+
*/
|
|
7
|
+
import { EventEmitter } from 'events';
|
|
8
|
+
import { DEFAULT_ZONES, } from './types.js';
|
|
9
|
+
export class ZoneManager extends EventEmitter {
|
|
10
|
+
zones = new Map();
|
|
11
|
+
agents = new Map();
|
|
12
|
+
constructor() {
|
|
13
|
+
super();
|
|
14
|
+
// Initialize default zones
|
|
15
|
+
this.initializeDefaultZones();
|
|
16
|
+
}
|
|
17
|
+
initializeDefaultZones() {
|
|
18
|
+
for (const config of DEFAULT_ZONES) {
|
|
19
|
+
this.createZone(config);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Create a new zone
|
|
24
|
+
*/
|
|
25
|
+
createZone(config) {
|
|
26
|
+
const zone = {
|
|
27
|
+
config,
|
|
28
|
+
status: 'idle',
|
|
29
|
+
memory: {
|
|
30
|
+
data: new Map(),
|
|
31
|
+
findings: [],
|
|
32
|
+
logs: [],
|
|
33
|
+
},
|
|
34
|
+
};
|
|
35
|
+
this.zones.set(config.id, zone);
|
|
36
|
+
this.emit('zone:created', { zoneId: config.id, zone });
|
|
37
|
+
return zone;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Get a zone by ID
|
|
41
|
+
*/
|
|
42
|
+
getZone(zoneId) {
|
|
43
|
+
return this.zones.get(zoneId);
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Get all zones
|
|
47
|
+
*/
|
|
48
|
+
getAllZones() {
|
|
49
|
+
return Array.from(this.zones.values());
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Register an agent
|
|
53
|
+
*/
|
|
54
|
+
registerAgent(agent) {
|
|
55
|
+
this.agents.set(agent.config.id, agent);
|
|
56
|
+
this.emit('agent:registered', { agentId: agent.config.id, agent });
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Get an agent by ID
|
|
60
|
+
*/
|
|
61
|
+
getAgent(agentId) {
|
|
62
|
+
return this.agents.get(agentId);
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Get all agents
|
|
66
|
+
*/
|
|
67
|
+
getAllAgents() {
|
|
68
|
+
return Array.from(this.agents.values());
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Get agents for a specific zone
|
|
72
|
+
*/
|
|
73
|
+
getZoneAgents(zoneId) {
|
|
74
|
+
const zone = this.zones.get(zoneId);
|
|
75
|
+
if (!zone)
|
|
76
|
+
return [];
|
|
77
|
+
return zone.config.agentIds
|
|
78
|
+
.map((id) => this.agents.get(id))
|
|
79
|
+
.filter((agent) => agent !== undefined);
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Assign an agent to a zone
|
|
83
|
+
*/
|
|
84
|
+
assignAgentToZone(agentId, zoneId) {
|
|
85
|
+
const zone = this.zones.get(zoneId);
|
|
86
|
+
if (!zone)
|
|
87
|
+
throw new Error(`Zone ${zoneId} not found`);
|
|
88
|
+
if (!zone.config.agentIds.includes(agentId)) {
|
|
89
|
+
zone.config.agentIds.push(agentId);
|
|
90
|
+
this.emit('agent:assigned', { agentId, zoneId });
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Remove an agent from a zone
|
|
95
|
+
*/
|
|
96
|
+
removeAgentFromZone(agentId, zoneId) {
|
|
97
|
+
const zone = this.zones.get(zoneId);
|
|
98
|
+
if (!zone)
|
|
99
|
+
return;
|
|
100
|
+
const index = zone.config.agentIds.indexOf(agentId);
|
|
101
|
+
if (index > -1) {
|
|
102
|
+
zone.config.agentIds.splice(index, 1);
|
|
103
|
+
this.emit('agent:removed', { agentId, zoneId });
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Create a zone context for agent execution
|
|
108
|
+
*/
|
|
109
|
+
createZoneContext(zone, targetPath) {
|
|
110
|
+
return {
|
|
111
|
+
zoneId: zone.config.id,
|
|
112
|
+
zoneName: zone.config.name,
|
|
113
|
+
zoneType: zone.config.type,
|
|
114
|
+
targetPath,
|
|
115
|
+
memory: zone.memory,
|
|
116
|
+
config: zone.config.config || {},
|
|
117
|
+
addFinding: (finding) => {
|
|
118
|
+
const fullFinding = {
|
|
119
|
+
...finding,
|
|
120
|
+
id: `${zone.config.id}-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`,
|
|
121
|
+
timestamp: Date.now(),
|
|
122
|
+
};
|
|
123
|
+
zone.memory.findings.push(fullFinding);
|
|
124
|
+
this.emit('finding:added', { zoneId: zone.config.id, finding: fullFinding });
|
|
125
|
+
},
|
|
126
|
+
log: (level, message) => {
|
|
127
|
+
const log = {
|
|
128
|
+
level,
|
|
129
|
+
message,
|
|
130
|
+
timestamp: Date.now(),
|
|
131
|
+
};
|
|
132
|
+
zone.memory.logs.push(log);
|
|
133
|
+
this.emit('zone:log', { zoneId: zone.config.id, log });
|
|
134
|
+
},
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Execute a single zone
|
|
139
|
+
*/
|
|
140
|
+
async executeZone(zoneId, targetPath) {
|
|
141
|
+
const zone = this.zones.get(zoneId);
|
|
142
|
+
if (!zone)
|
|
143
|
+
throw new Error(`Zone ${zoneId} not found`);
|
|
144
|
+
// Update zone status
|
|
145
|
+
zone.status = 'running';
|
|
146
|
+
zone.startTime = Date.now();
|
|
147
|
+
zone.memory.findings = [];
|
|
148
|
+
zone.memory.logs = [];
|
|
149
|
+
this.emit('zone:started', { zoneId });
|
|
150
|
+
const context = this.createZoneContext(zone, targetPath);
|
|
151
|
+
const agentResults = [];
|
|
152
|
+
try {
|
|
153
|
+
// Get agents for this zone
|
|
154
|
+
const agents = this.getZoneAgents(zoneId);
|
|
155
|
+
// Execute all agents in parallel within the zone
|
|
156
|
+
const results = await Promise.all(agents.map(async (agent) => {
|
|
157
|
+
const agentStartTime = Date.now();
|
|
158
|
+
try {
|
|
159
|
+
// Check if agent is available
|
|
160
|
+
const isAvailable = await agent.isAvailable();
|
|
161
|
+
if (!isAvailable) {
|
|
162
|
+
context.log('warn', `Agent ${agent.config.name} not available, skipping`);
|
|
163
|
+
return {
|
|
164
|
+
agentId: agent.config.id,
|
|
165
|
+
agentName: agent.config.name,
|
|
166
|
+
status: 'skipped',
|
|
167
|
+
findings: [],
|
|
168
|
+
duration: Date.now() - agentStartTime,
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
this.emit('agent:started', { zoneId, agentId: agent.config.id });
|
|
172
|
+
context.log('info', `Starting agent: ${agent.config.name}`);
|
|
173
|
+
const result = await agent.execute(context);
|
|
174
|
+
this.emit('agent:completed', { zoneId, agentId: agent.config.id, result });
|
|
175
|
+
context.log('info', `Agent ${agent.config.name} completed with ${result.findings.length} findings`);
|
|
176
|
+
return result;
|
|
177
|
+
}
|
|
178
|
+
catch (error) {
|
|
179
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
180
|
+
context.log('error', `Agent ${agent.config.name} failed: ${errorMsg}`);
|
|
181
|
+
this.emit('agent:error', { zoneId, agentId: agent.config.id, error: errorMsg });
|
|
182
|
+
return {
|
|
183
|
+
agentId: agent.config.id,
|
|
184
|
+
agentName: agent.config.name,
|
|
185
|
+
status: 'error',
|
|
186
|
+
findings: [],
|
|
187
|
+
duration: Date.now() - agentStartTime,
|
|
188
|
+
error: errorMsg,
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
}));
|
|
192
|
+
agentResults.push(...results);
|
|
193
|
+
zone.status = 'complete';
|
|
194
|
+
zone.endTime = Date.now();
|
|
195
|
+
this.emit('zone:completed', { zoneId });
|
|
196
|
+
}
|
|
197
|
+
catch (error) {
|
|
198
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
199
|
+
zone.status = 'error';
|
|
200
|
+
zone.error = errorMsg;
|
|
201
|
+
zone.endTime = Date.now();
|
|
202
|
+
this.emit('zone:error', { zoneId, error: errorMsg });
|
|
203
|
+
}
|
|
204
|
+
return {
|
|
205
|
+
zoneId: zone.config.id,
|
|
206
|
+
zoneName: zone.config.name,
|
|
207
|
+
zoneType: zone.config.type,
|
|
208
|
+
status: zone.status,
|
|
209
|
+
findings: zone.memory.findings,
|
|
210
|
+
logs: zone.memory.logs,
|
|
211
|
+
duration: (zone.endTime || Date.now()) - (zone.startTime || Date.now()),
|
|
212
|
+
agentResults,
|
|
213
|
+
error: zone.error,
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* Execute multiple zones in parallel
|
|
218
|
+
*/
|
|
219
|
+
async executeZonesParallel(zoneIds, targetPath) {
|
|
220
|
+
this.emit('execution:started', { zoneIds, targetPath });
|
|
221
|
+
const results = await Promise.all(zoneIds.map((zoneId) => this.executeZone(zoneId, targetPath)));
|
|
222
|
+
const resultMap = new Map();
|
|
223
|
+
for (const result of results) {
|
|
224
|
+
resultMap.set(result.zoneId, result);
|
|
225
|
+
}
|
|
226
|
+
this.emit('execution:completed', { results: resultMap });
|
|
227
|
+
return resultMap;
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* Execute all zones in parallel
|
|
231
|
+
*/
|
|
232
|
+
async executeAllZones(targetPath) {
|
|
233
|
+
const zoneIds = Array.from(this.zones.keys());
|
|
234
|
+
return this.executeZonesParallel(zoneIds, targetPath);
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* Reset a zone to idle state
|
|
238
|
+
*/
|
|
239
|
+
resetZone(zoneId) {
|
|
240
|
+
const zone = this.zones.get(zoneId);
|
|
241
|
+
if (!zone)
|
|
242
|
+
return;
|
|
243
|
+
zone.status = 'idle';
|
|
244
|
+
zone.startTime = undefined;
|
|
245
|
+
zone.endTime = undefined;
|
|
246
|
+
zone.error = undefined;
|
|
247
|
+
zone.memory = {
|
|
248
|
+
data: new Map(),
|
|
249
|
+
findings: [],
|
|
250
|
+
logs: [],
|
|
251
|
+
};
|
|
252
|
+
this.emit('zone:reset', { zoneId });
|
|
253
|
+
}
|
|
254
|
+
/**
|
|
255
|
+
* Get zone status
|
|
256
|
+
*/
|
|
257
|
+
getZoneStatus(zoneId) {
|
|
258
|
+
return this.zones.get(zoneId)?.status;
|
|
259
|
+
}
|
|
260
|
+
/**
|
|
261
|
+
* Get all findings from all zones
|
|
262
|
+
*/
|
|
263
|
+
getAllFindings() {
|
|
264
|
+
const findings = [];
|
|
265
|
+
for (const zone of this.zones.values()) {
|
|
266
|
+
findings.push(...zone.memory.findings);
|
|
267
|
+
}
|
|
268
|
+
return findings;
|
|
269
|
+
}
|
|
270
|
+
/**
|
|
271
|
+
* Export zone state for visualization
|
|
272
|
+
*/
|
|
273
|
+
exportState() {
|
|
274
|
+
const zones = Array.from(this.zones.values()).map((zone) => ({
|
|
275
|
+
id: zone.config.id,
|
|
276
|
+
name: zone.config.name,
|
|
277
|
+
type: zone.config.type,
|
|
278
|
+
color: zone.config.color,
|
|
279
|
+
status: zone.status,
|
|
280
|
+
agentCount: zone.config.agentIds.length,
|
|
281
|
+
findingCount: zone.memory.findings.length,
|
|
282
|
+
}));
|
|
283
|
+
const agents = Array.from(this.agents.values()).map((agent) => {
|
|
284
|
+
// Find which zone this agent belongs to
|
|
285
|
+
let zoneId = null;
|
|
286
|
+
for (const zone of this.zones.values()) {
|
|
287
|
+
if (zone.config.agentIds.includes(agent.config.id)) {
|
|
288
|
+
zoneId = zone.config.id;
|
|
289
|
+
break;
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
return {
|
|
293
|
+
id: agent.config.id,
|
|
294
|
+
name: agent.config.name,
|
|
295
|
+
role: agent.config.role,
|
|
296
|
+
zoneId,
|
|
297
|
+
status: agent.getStatus(),
|
|
298
|
+
};
|
|
299
|
+
});
|
|
300
|
+
return { zones, agents };
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
// Export singleton instance
|
|
304
|
+
export const zoneManager = new ZoneManager();
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Aura Protocol - Zone Types
|
|
3
|
+
*
|
|
4
|
+
* Zones are isolated execution environments that contain agents.
|
|
5
|
+
* Each zone has its own memory space and can run in parallel with other zones.
|
|
6
|
+
*/
|
|
7
|
+
export type ZoneStatus = 'idle' | 'running' | 'complete' | 'error';
|
|
8
|
+
export type ZoneType = 'scanner' | 'policy' | 'remediation' | 'reporting';
|
|
9
|
+
export interface ZoneConfig {
|
|
10
|
+
id: string;
|
|
11
|
+
name: string;
|
|
12
|
+
type: ZoneType;
|
|
13
|
+
color: string;
|
|
14
|
+
description?: string;
|
|
15
|
+
agentIds: string[];
|
|
16
|
+
config?: Record<string, unknown>;
|
|
17
|
+
}
|
|
18
|
+
export interface ZoneMemory {
|
|
19
|
+
data: Map<string, unknown>;
|
|
20
|
+
findings: ZoneFinding[];
|
|
21
|
+
logs: ZoneLog[];
|
|
22
|
+
}
|
|
23
|
+
export interface ZoneFinding {
|
|
24
|
+
id: string;
|
|
25
|
+
agentId: string;
|
|
26
|
+
type: 'secret' | 'vulnerability' | 'policy_violation' | 'recommendation';
|
|
27
|
+
severity: 'critical' | 'high' | 'medium' | 'low' | 'info';
|
|
28
|
+
title: string;
|
|
29
|
+
description: string;
|
|
30
|
+
file?: string;
|
|
31
|
+
line?: number;
|
|
32
|
+
metadata?: Record<string, unknown>;
|
|
33
|
+
timestamp: number;
|
|
34
|
+
}
|
|
35
|
+
export interface ZoneLog {
|
|
36
|
+
level: 'debug' | 'info' | 'warn' | 'error';
|
|
37
|
+
message: string;
|
|
38
|
+
agentId?: string;
|
|
39
|
+
timestamp: number;
|
|
40
|
+
}
|
|
41
|
+
export interface Zone {
|
|
42
|
+
config: ZoneConfig;
|
|
43
|
+
status: ZoneStatus;
|
|
44
|
+
memory: ZoneMemory;
|
|
45
|
+
startTime?: number;
|
|
46
|
+
endTime?: number;
|
|
47
|
+
error?: string;
|
|
48
|
+
}
|
|
49
|
+
export interface ZoneResult {
|
|
50
|
+
zoneId: string;
|
|
51
|
+
zoneName: string;
|
|
52
|
+
zoneType: ZoneType;
|
|
53
|
+
status: ZoneStatus;
|
|
54
|
+
findings: ZoneFinding[];
|
|
55
|
+
logs: ZoneLog[];
|
|
56
|
+
duration: number;
|
|
57
|
+
agentResults: AgentResult[];
|
|
58
|
+
error?: string;
|
|
59
|
+
}
|
|
60
|
+
export interface AgentResult {
|
|
61
|
+
agentId: string;
|
|
62
|
+
agentName: string;
|
|
63
|
+
status: 'success' | 'error' | 'skipped';
|
|
64
|
+
findings: ZoneFinding[];
|
|
65
|
+
duration: number;
|
|
66
|
+
error?: string;
|
|
67
|
+
}
|
|
68
|
+
export interface ZoneContext {
|
|
69
|
+
zoneId: string;
|
|
70
|
+
zoneName: string;
|
|
71
|
+
zoneType: ZoneType;
|
|
72
|
+
targetPath: string;
|
|
73
|
+
memory: ZoneMemory;
|
|
74
|
+
config: Record<string, unknown>;
|
|
75
|
+
addFinding: (finding: Omit<ZoneFinding, 'id' | 'timestamp'>) => void;
|
|
76
|
+
log: (level: ZoneLog['level'], message: string) => void;
|
|
77
|
+
}
|
|
78
|
+
export declare const DEFAULT_ZONES: ZoneConfig[];
|