// Copyright (C) 2025 Keygraph, Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License version 3 // as published by the Free Software Foundation. import { fs, path } from 'zx'; import { validateQueueAndDeliverable } from './services/queue-validation.js'; import type { ActivityLogger } from './types/activity-logger.js'; import type { AgentDefinition, AgentName, AgentValidator, PlaywrightSession, VulnType } from './types/index.js'; // Agent definitions according to PRD export const AGENTS: Readonly> = Object.freeze({ 'pre-recon': { name: 'pre-recon', displayName: 'Pre-recon agent', prerequisites: [], promptTemplate: 'pre-recon-code', deliverableFilename: 'pre_recon_deliverable.md', modelTier: 'large', }, recon: { name: 'recon', displayName: 'Recon agent', prerequisites: ['pre-recon'], promptTemplate: 'recon', deliverableFilename: 'recon_deliverable.md', }, 'injection-vuln': { name: 'injection-vuln', displayName: 'Injection vuln agent', prerequisites: ['recon'], promptTemplate: 'vuln-injection', deliverableFilename: 'injection_analysis_deliverable.md', }, 'xss-vuln': { name: 'xss-vuln', displayName: 'XSS vuln agent', prerequisites: ['recon'], promptTemplate: 'vuln-xss', deliverableFilename: 'xss_analysis_deliverable.md', }, 'auth-vuln': { name: 'auth-vuln', displayName: 'Auth vuln agent', prerequisites: ['recon'], promptTemplate: 'vuln-auth', deliverableFilename: 'auth_analysis_deliverable.md', }, 'ssrf-vuln': { name: 'ssrf-vuln', displayName: 'SSRF vuln agent', prerequisites: ['recon'], promptTemplate: 'vuln-ssrf', deliverableFilename: 'ssrf_analysis_deliverable.md', }, 'authz-vuln': { name: 'authz-vuln', displayName: 'Authz vuln agent', prerequisites: ['recon'], promptTemplate: 'vuln-authz', deliverableFilename: 'authz_analysis_deliverable.md', }, 'injection-exploit': { name: 'injection-exploit', displayName: 'Injection exploit agent', prerequisites: ['injection-vuln'], promptTemplate: 'exploit-injection', deliverableFilename: 'injection_exploitation_evidence.md', }, 'xss-exploit': { name: 'xss-exploit', displayName: 'XSS exploit agent', prerequisites: ['xss-vuln'], promptTemplate: 'exploit-xss', deliverableFilename: 'xss_exploitation_evidence.md', }, 'auth-exploit': { name: 'auth-exploit', displayName: 'Auth exploit agent', prerequisites: ['auth-vuln'], promptTemplate: 'exploit-auth', deliverableFilename: 'auth_exploitation_evidence.md', }, 'ssrf-exploit': { name: 'ssrf-exploit', displayName: 'SSRF exploit agent', prerequisites: ['ssrf-vuln'], promptTemplate: 'exploit-ssrf', deliverableFilename: 'ssrf_exploitation_evidence.md', }, 'authz-exploit': { name: 'authz-exploit', displayName: 'Authz exploit agent', prerequisites: ['authz-vuln'], promptTemplate: 'exploit-authz', deliverableFilename: 'authz_exploitation_evidence.md', }, report: { name: 'report', displayName: 'Report agent', prerequisites: ['injection-exploit', 'xss-exploit', 'auth-exploit', 'ssrf-exploit', 'authz-exploit'], promptTemplate: 'report-executive', deliverableFilename: 'comprehensive_security_assessment_report.md', modelTier: 'small', }, }); // Phase names for metrics aggregation export type PhaseName = 'pre-recon' | 'recon' | 'vulnerability-analysis' | 'exploitation' | 'reporting'; // Map agents to their corresponding phases (single source of truth) export const AGENT_PHASE_MAP: Readonly> = Object.freeze({ 'pre-recon': 'pre-recon', recon: 'recon', 'injection-vuln': 'vulnerability-analysis', 'xss-vuln': 'vulnerability-analysis', 'auth-vuln': 'vulnerability-analysis', 'authz-vuln': 'vulnerability-analysis', 'ssrf-vuln': 'vulnerability-analysis', 'injection-exploit': 'exploitation', 'xss-exploit': 'exploitation', 'auth-exploit': 'exploitation', 'authz-exploit': 'exploitation', 'ssrf-exploit': 'exploitation', report: 'reporting', }); // Factory function for vulnerability queue validators function createVulnValidator(vulnType: VulnType): AgentValidator { return async (sourceDir: string, logger: ActivityLogger): Promise => { try { await validateQueueAndDeliverable(vulnType, sourceDir); return true; } catch (error) { const errMsg = error instanceof Error ? error.message : String(error); logger.warn(`Queue validation failed for ${vulnType}: ${errMsg}`); return false; } }; } // Factory function for exploit deliverable validators function createExploitValidator(vulnType: VulnType): AgentValidator { return async (sourceDir: string): Promise => { const evidenceFile = path.join(sourceDir, '.shannon', 'deliverables', `${vulnType}_exploitation_evidence.md`); return await fs.pathExists(evidenceFile); }; } // Playwright session mapping - assigns each agent to a specific session for browser isolation // Keys are promptTemplate values from AGENTS registry export const PLAYWRIGHT_SESSION_MAPPING: Record = Object.freeze({ // Phase 1: Pre-reconnaissance 'pre-recon-code': 'agent1', // Phase 2: Reconnaissance recon: 'agent2', // Phase 3: Vulnerability Analysis (5 parallel agents) 'vuln-injection': 'agent1', 'vuln-xss': 'agent2', 'vuln-auth': 'agent3', 'vuln-ssrf': 'agent4', 'vuln-authz': 'agent5', // Phase 4: Exploitation (5 parallel agents - same as vuln counterparts) 'exploit-injection': 'agent1', 'exploit-xss': 'agent2', 'exploit-auth': 'agent3', 'exploit-ssrf': 'agent4', 'exploit-authz': 'agent5', // Phase 5: Reporting 'report-executive': 'agent3', }); // Direct agent-to-validator mapping - much simpler than pattern matching export const AGENT_VALIDATORS: Record = Object.freeze({ // Pre-reconnaissance agent - validates the code analysis deliverable created by the agent 'pre-recon': async (sourceDir: string): Promise => { const codeAnalysisFile = path.join(sourceDir, '.shannon', 'deliverables', 'pre_recon_deliverable.md'); return await fs.pathExists(codeAnalysisFile); }, // Reconnaissance agent recon: async (sourceDir: string): Promise => { const reconFile = path.join(sourceDir, '.shannon', 'deliverables', 'recon_deliverable.md'); return await fs.pathExists(reconFile); }, // Vulnerability analysis agents 'injection-vuln': createVulnValidator('injection'), 'xss-vuln': createVulnValidator('xss'), 'auth-vuln': createVulnValidator('auth'), 'ssrf-vuln': createVulnValidator('ssrf'), 'authz-vuln': createVulnValidator('authz'), // Exploitation agents 'injection-exploit': createExploitValidator('injection'), 'xss-exploit': createExploitValidator('xss'), 'auth-exploit': createExploitValidator('auth'), 'ssrf-exploit': createExploitValidator('ssrf'), 'authz-exploit': createExploitValidator('authz'), // Executive report agent report: async (sourceDir: string, logger: ActivityLogger): Promise => { const reportFile = path.join(sourceDir, '.shannon', 'deliverables', 'comprehensive_security_assessment_report.md'); const reportExists = await fs.pathExists(reportFile); if (!reportExists) { logger.error('Missing required deliverable: comprehensive_security_assessment_report.md'); } return reportExists; }, });