@@ -174,7 +174,7 @@ var subdomainWorkflowPhaseSpecs = []workflowPhaseSpec{
174174 {Module : "tech-detect" , Description : "[Stage 2] Technology detection" , PhaseKey : "tech" },
175175 {Module : "port-scan" , Description : "[Stage 2] Port scan" , PhaseKey : "ports" },
176176 {Module : "url-collection" , Description : "[Stage 2] URL collection" , PhaseKey : "urls" },
177- {Module : "js-analysis" , Description : "[Stage 2] JS scan" , PhaseKey : "js-analysis" },
177+ {Module : "js-analysis" , Description : "[Stage 2] JS secrets scan" , PhaseKey : "js-analysis" },
178178 {Module : "aem" , Description : "[Stage 2] AEM scan" , PhaseKey : "aem" },
179179 {Module : "dns-takeover" , Description : "[Stage 2] DNS scan" , PhaseKey : "dns" },
180180 {Module : "s3-scan" , Description : "[Stage 2] S3 bucket enumeration and scanning" , PhaseKey : "s3" },
@@ -183,16 +183,36 @@ var subdomainWorkflowPhaseSpecs = []workflowPhaseSpec{
183183 {Module : "wordpress-confusion" , Description : "[Stage 2] WordPress confusion" , PhaseKey : "wp_confusion" },
184184 {Module : "dependency-confusion" , Description : "[Stage 2] Dependency confusion" , PhaseKey : "depconfusion" },
185185 {Module : "misconfig" , Description : "[Stage 2] Misconfig scan" , PhaseKey : "misconfig" },
186- {Module : "js-endpoints" , Description : "[Stage 2] JS Endpoints" , PhaseKey : "js-endpoints" },
187- {Module : "github-scan" , Description : "[Stage 2] GitHub Secrets" , PhaseKey : "github-scan" },
188186 {Module : "katana" , Description : "[Stage 2.5] Katana crawler" , PhaseKey : "katana" },
189187 {Module : "gf-patterns" , Description : "[Stage 3] GF scan" , PhaseKey : "gf" },
188+ {Module : "js-endpoints" , Description : "[Stage 3] JS endpoint extraction" , PhaseKey : "js-endpoints" },
190189 {Module : "reflection" , Description : "[Stage 3] Reflection scan" , PhaseKey : "reflection" },
191190 {Module : "ffuf-fuzzing" , Description : "[Stage 3] FFuf fuzzing" , PhaseKey : "ffuf" },
192191 {Module : "nuclei" , Description : "[Stage 3] Nuclei scan (final)" , PhaseKey : "nuclei" },
193192 {Module : "xss-detection" , Description : "[Stage 4] Dalfox XSS confirmation" , PhaseKey : "xss-detection" },
194193}
195194
195+ var domainWorkflowPhaseSpecs = []workflowPhaseSpec {
196+ {Module : "subdomain-enum" , Description : "Subdomain enumeration" , PhaseKey : "subdomains" },
197+ {Module : "dns-takeover" , Description : "CNAME collection" , PhaseKey : "cnames" },
198+ {Module : "httpx" , Description : "Live host filtering" , PhaseKey : "livehosts" },
199+ {Module : "tech-detect" , Description : "Technology detection" , PhaseKey : "tech" },
200+ {Module : "port-scan" , Description : "Port scanning" , PhaseKey : "ports" },
201+ {Module : "url-collection" , Description : "URL collection" , PhaseKey : "urls" },
202+ {Module : "js-analysis" , Description : "JavaScript scan" , PhaseKey : "jsscan" },
203+ {Module : "dns-takeover" , Description : "DNS takeover scan" , PhaseKey : "dns" },
204+ {Module : "aem" , Description : "AEM webapp discovery and scan" , PhaseKey : "aem" },
205+ {Module : "wordpress-confusion" , Description : "WordPress confusion scan" , PhaseKey : "wp_confusion" },
206+ {Module : "dependency-confusion" , Description : "Dependency confusion scan" , PhaseKey : "depconfusion" },
207+ {Module : "s3-scan" , Description : "S3 bucket enumeration" , PhaseKey : "s3" },
208+ {Module : "backup-detection" , Description : "Backup file discovery" , PhaseKey : "backup" },
209+ {Module : "misconfig" , Description : "Cloud misconfiguration scan" , PhaseKey : "misconfig" },
210+ {Module : "reflection" , Description : "Reflection scan" , PhaseKey : "reflection" },
211+ {Module : "gf-patterns" , Description : "GF pattern matching" , PhaseKey : "gf" },
212+ {Module : "nuclei" , Description : "Nuclei scan" , PhaseKey : "nuclei" },
213+ {Module : "ffuf-fuzzing" , Description : "FFuf fuzzing" , PhaseKey : "ffuf" },
214+ }
215+
196216
197217func workflowPhaseManifestModules (rec * db.ScanRecord ) []moduleExecutionEntry {
198218 if rec == nil {
@@ -206,7 +226,13 @@ func workflowPhaseManifestModules(rec *db.ScanRecord) []moduleExecutionEntry {
206226 completed := stringSet (rec .CompletedPhases )
207227 failed := stringSet (rec .FailedPhases )
208228 outputsByModule := collectScanOutputFilesByModule (rec .ScanID )
209- modules := make ([]moduleExecutionEntry , 0 , len (subdomainWorkflowPhaseSpecs ))
229+
230+ // Select the correct phase spec based on scan type.
231+ specs := subdomainWorkflowPhaseSpecs
232+ if scanType == "domain_run" {
233+ specs = domainWorkflowPhaseSpecs
234+ }
235+ modules := make ([]moduleExecutionEntry , 0 , len (specs ))
210236 now := time .Now ()
211237
212238 // Determine overall scan state for smart inference.
@@ -216,12 +242,15 @@ func workflowPhaseManifestModules(rec *db.ScanRecord) []moduleExecutionEntry {
216242 scanFailed := strings .EqualFold (strings .TrimSpace (rec .Status ), "failed" ) ||
217243 strings .EqualFold (strings .TrimSpace (rec .Status ), "error" )
218244
219- for _ , spec := range subdomainWorkflowPhaseSpecs {
245+ for _ , spec := range specs {
220246 status := "pending"
221247 completedAt := time.Time {}
222248 durationMS := int64 (0 )
223249
224- phaseFiles := outputsByModule [spec .Module ]
250+ phaseFiles := outputsByModule [spec .PhaseKey ]
251+ if len (phaseFiles ) == 0 {
252+ phaseFiles = outputsByModule [spec .Module ]
253+ }
225254 hasArtifacts := len (phaseFiles ) > 0
226255
227256 if _ , ok := completed [spec .Description ]; ok {
@@ -365,7 +394,7 @@ func inferModuleFromFileName(name string) string {
365394 return "url-collection"
366395 // katana crawler results — separate from general URL collection
367396 case strings .Contains (n , "katana" ):
368- return "katana-crawler "
397+ return "katana"
369398 // js-endpoints: API path extraction results from JS files
370399 case strings .Contains (n , "js-endpoint" ):
371400 return "js-endpoints"
@@ -397,7 +426,7 @@ func inferModuleFromFileName(name string) string {
397426 case strings .Contains (n , "port-scan" ) || strings .Contains (n , "ports" ) || strings .Contains (n , "nmap" ) || strings .Contains (n , "masscan" ):
398427 return "port-scan"
399428 case strings .Contains (n , "aem" ):
400- return "aem-scan "
429+ return "aem"
401430 case strings .Contains (n , "github" ) || strings .Contains (n , "github-scan" ) || strings .Contains (n , "gh-" ) || strings .Contains (n , "github-secrets" ) || strings .Contains (n , "secrets_table" ) || (strings .Contains (n , "secrets" ) && strings .HasSuffix (n , ".json" )):
402431 return "github-scan"
403432 case strings .Contains (n , "backup" ) || strings .Contains (n , "fuzzuli" ):
@@ -413,7 +442,7 @@ func inferModuleFromFileName(name string) string {
413442 case strings .HasSuffix (n , "urls.txt" ) || strings .Contains (n , "all-urls.txt" ) || strings .Contains (n , "wayback" ):
414443 return "url-collection"
415444 case strings .Contains (n , "js-url" ) || strings .Contains (n , "js_url" ) || strings .Contains (n , "js-enum" ):
416- return "JS-Enum "
445+ return "url-collection "
417446 case strings .HasSuffix (n , "urls.json" ) || strings .HasSuffix (n , "urls.txt" ) || strings .Contains (n , "all-urls.txt" ) || strings .Contains (n , "wayback" ):
418447 return "url-collection"
419448 default :
@@ -1744,9 +1773,7 @@ func parseArtifactFindings(raw []byte, module, category string, maxRows int) []p
17441773 }
17451774 case string :
17461775 fT := "Recon"
1747- if module == "JS-Enum" {
1748- fT = "JS-Enum"
1749- } else if module == "url-collection" {
1776+ if module == "url-collection" {
17501777 fT = "URL-Collection"
17511778 } else {
17521779 fT = module
@@ -1792,9 +1819,7 @@ func parseArtifactFindings(raw []byte, module, category string, maxRows int) []p
17921819 continue
17931820 }
17941821 fT := "Recon"
1795- if module == "JS-Enum" {
1796- fT = "JS-Enum"
1797- } else if module == "url-collection" {
1822+ if module == "url-collection" {
17981823 fT = "URL-Collection"
17991824 } else {
18001825 fT = module
0 commit comments