fase(5): findings module complete
Some checks failed
ABE Exploratory Testing / explore (push) Has been cancelled

This commit is contained in:
debian
2026-03-05 04:06:45 -05:00
parent 96bf6e5097
commit d62bd615bf
55 changed files with 2424 additions and 48 deletions

View File

@@ -0,0 +1,50 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.CreateFindingCommand = void 0;
const Result_1 = require("../../../../shared/domain/Result");
const Finding_1 = require("../../domain/entities/Finding");
const Severity_1 = require("../../domain/value-objects/Severity");
const FindingType_1 = require("../../domain/value-objects/FindingType");
const Evidence_1 = require("../../domain/value-objects/Evidence");
class CreateFindingCommand {
constructor(repository, eventBus) {
this.repository = repository;
this.eventBus = eventBus;
}
async execute(request) {
let severity;
let type;
try {
severity = Severity_1.Severity.fromString(request.anomaly.severity);
type = FindingType_1.FindingType.fromString(request.anomaly.type);
}
catch (e) {
return (0, Result_1.Err)(e instanceof Error ? e.message : String(e));
}
const evidence = Evidence_1.Evidence.create({
screenshotPath: request.anomaly.evidence.screenshotPath,
domSnapshotPath: request.anomaly.evidence.domSnapshotPath,
httpLog: request.anomaly.evidence.httpLog,
rawErrors: request.anomaly.evidence.rawErrors,
});
const finding = Finding_1.Finding.create({
sessionId: request.sessionId,
severity,
type,
description: request.anomaly.description,
evidence,
actionTrace: request.anomaly.actionTrace,
browser: request.anomaly.browser,
browserVersion: request.anomaly.browserVersion,
aiEnrichment: request.anomaly.aiEnrichment,
});
await this.repository.save(finding);
const events = finding.domainEvents;
for (const event of events) {
await this.eventBus.publish(event);
}
finding.clearEvents();
return (0, Result_1.Ok)({ findingId: finding.id.toString() });
}
}
exports.CreateFindingCommand = CreateFindingCommand;

View File

@@ -0,0 +1,33 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.EnrichFindingCommand = void 0;
const Result_1 = require("../../../../shared/domain/Result");
class EnrichFindingCommand {
constructor(repository, enricher, eventBus) {
this.repository = repository;
this.enricher = enricher;
this.eventBus = eventBus;
}
async execute(request) {
const finding = await this.repository.findById(request.findingId);
if (!finding) {
return (0, Result_1.Err)(`Finding not found: ${request.findingId}`);
}
let enrichment;
try {
enrichment = await this.enricher.enrich(finding);
}
catch (e) {
return (0, Result_1.Err)(`Enrichment failed: ${e instanceof Error ? e.message : String(e)}`);
}
finding.enrich(enrichment);
await this.repository.update(finding);
const events = finding.domainEvents;
for (const event of events) {
await this.eventBus.publish(event);
}
finding.clearEvents();
return (0, Result_1.Ok)({ findingId: finding.id.toString() });
}
}
exports.EnrichFindingCommand = EnrichFindingCommand;

View File

@@ -0,0 +1,35 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ResolveFindingCommand = void 0;
const Result_1 = require("../../../../shared/domain/Result");
class ResolveFindingCommand {
constructor(repository, eventBus) {
this.repository = repository;
this.eventBus = eventBus;
}
async execute(request) {
const finding = await this.repository.findById(request.findingId);
if (!finding) {
return (0, Result_1.Err)(`Finding not found: ${request.findingId}`);
}
switch (request.action) {
case 'resolve':
finding.resolve();
break;
case 'close':
finding.close();
break;
case 'investigate':
finding.investigate();
break;
}
await this.repository.update(finding);
const events = finding.domainEvents;
for (const event of events) {
await this.eventBus.publish(event);
}
finding.clearEvents();
return (0, Result_1.Ok)({ findingId: finding.id.toString(), status: finding.status.value });
}
}
exports.ResolveFindingCommand = ResolveFindingCommand;

View File

@@ -0,0 +1,22 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.OnAnomalyDetected = void 0;
/**
* Listens for anomaly_detected events from crawling module
* and creates a Finding in the findings module.
*/
class OnAnomalyDetected {
constructor(createFinding) {
this.createFinding = createFinding;
}
async handle(event) {
const payload = event.payload;
if (!payload.anomaly || !payload.sessionId)
return;
await this.createFinding.execute({
anomaly: payload.anomaly,
sessionId: payload.sessionId,
});
}
}
exports.OnAnomalyDetected = OnAnomalyDetected;

View File

@@ -0,0 +1,19 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.FindingStatsQuery = void 0;
const Result_1 = require("../../../../shared/domain/Result");
class FindingStatsQuery {
constructor(repository) {
this.repository = repository;
}
async execute(request) {
const [total, bySeverity, openCount, resolvedCount] = await Promise.all([
this.repository.count(request.sessionId ? { sessionId: request.sessionId } : undefined),
this.repository.countBySeverity(),
this.repository.count({ status: 'open', sessionId: request.sessionId }),
this.repository.count({ status: 'resolved', sessionId: request.sessionId }),
]);
return (0, Result_1.Ok)({ total, bySeverity, openCount, resolvedCount });
}
}
exports.FindingStatsQuery = FindingStatsQuery;

View File

@@ -0,0 +1,17 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.GetFindingQuery = void 0;
const Result_1 = require("../../../../shared/domain/Result");
class GetFindingQuery {
constructor(repository) {
this.repository = repository;
}
async execute(request) {
const finding = await this.repository.findById(request.findingId);
if (!finding) {
return (0, Result_1.Err)(`Finding not found: ${request.findingId}`);
}
return (0, Result_1.Ok)(finding);
}
}
exports.GetFindingQuery = GetFindingQuery;

View File

@@ -0,0 +1,22 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ListFindingsQuery = void 0;
const Result_1 = require("../../../../shared/domain/Result");
class ListFindingsQuery {
constructor(repository) {
this.repository = repository;
}
async execute(request) {
const filters = {
sessionId: request.sessionId,
severity: request.severity,
type: request.type,
status: request.status,
search: request.search,
};
const findings = await this.repository.findAll(filters);
const total = await this.repository.count(filters);
return (0, Result_1.Ok)({ findings, total });
}
}
exports.ListFindingsQuery = ListFindingsQuery;