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,64 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Finding = void 0;
const AggregateRoot_1 = require("../../../../shared/domain/AggregateRoot");
const UniqueId_1 = require("../../../../shared/domain/UniqueId");
const FindingStatus_1 = require("../value-objects/FindingStatus");
const FindingCreated_1 = require("../events/FindingCreated");
const FindingResolved_1 = require("../events/FindingResolved");
const FindingEnriched_1 = require("../events/FindingEnriched");
class Finding extends AggregateRoot_1.AggregateRoot {
static create(props, id) {
const findingId = id ?? UniqueId_1.UniqueId.create();
const finding = new Finding({
...props,
status: FindingStatus_1.FindingStatus.open(),
createdAt: new Date(),
}, findingId);
finding.addDomainEvent(new FindingCreated_1.FindingCreated(findingId.toString(), {
sessionId: props.sessionId,
severity: props.severity.value,
type: props.type.value,
description: props.description,
}));
return finding;
}
static reconstitute(props, id) {
return new Finding(props, id);
}
get sessionId() { return this.props.sessionId; }
get severity() { return this.props.severity; }
get type() { return this.props.type; }
get description() { return this.props.description; }
get evidence() { return this.props.evidence; }
get status() { return this.props.status; }
get actionTrace() { return this.props.actionTrace; }
get browser() { return this.props.browser; }
get browserVersion() { return this.props.browserVersion; }
get aiEnrichment() { return this.props.aiEnrichment; }
get createdAt() { return this.props.createdAt; }
get resolvedAt() { return this.props.resolvedAt; }
resolve() {
this.props.status = FindingStatus_1.FindingStatus.resolved();
this.props.resolvedAt = new Date();
this.addDomainEvent(new FindingResolved_1.FindingResolved(this.id.toString(), {
sessionId: this.props.sessionId,
resolvedAt: this.props.resolvedAt.toISOString(),
}));
}
close() {
this.props.status = FindingStatus_1.FindingStatus.closed();
}
investigate() {
this.props.status = FindingStatus_1.FindingStatus.investigating();
}
enrich(enrichment) {
this.props.aiEnrichment = enrichment;
this.addDomainEvent(new FindingEnriched_1.FindingEnriched(this.id.toString(), {
provider: enrichment.provider,
model: enrichment.model,
confidence: enrichment.confidence,
}));
}
}
exports.Finding = Finding;

View File

@@ -0,0 +1,14 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.FindingCreated = void 0;
const crypto_1 = require("crypto");
class FindingCreated {
constructor(aggregateId, payload) {
this.aggregateId = aggregateId;
this.payload = payload;
this.eventId = (0, crypto_1.randomUUID)();
this.eventName = 'finding.created';
this.occurredOn = new Date();
}
}
exports.FindingCreated = FindingCreated;

View File

@@ -0,0 +1,14 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.FindingEnriched = void 0;
const crypto_1 = require("crypto");
class FindingEnriched {
constructor(aggregateId, payload) {
this.aggregateId = aggregateId;
this.payload = payload;
this.eventId = (0, crypto_1.randomUUID)();
this.eventName = 'finding.enriched';
this.occurredOn = new Date();
}
}
exports.FindingEnriched = FindingEnriched;

View File

@@ -0,0 +1,14 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.FindingResolved = void 0;
const crypto_1 = require("crypto");
class FindingResolved {
constructor(aggregateId, payload) {
this.aggregateId = aggregateId;
this.payload = payload;
this.eventId = (0, crypto_1.randomUUID)();
this.eventName = 'finding.resolved';
this.occurredOn = new Date();
}
}
exports.FindingResolved = FindingResolved;

View File

@@ -0,0 +1,2 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });

View File

@@ -0,0 +1,2 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });

View File

@@ -0,0 +1,25 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Evidence = void 0;
const ValueObject_1 = require("../../../../shared/domain/ValueObject");
class Evidence extends ValueObject_1.ValueObject {
static create(props) {
return new Evidence(props);
}
static empty() {
return new Evidence({});
}
get screenshotPath() { return this.props.screenshotPath; }
get domSnapshotPath() { return this.props.domSnapshotPath; }
get httpLog() { return this.props.httpLog ?? []; }
get rawErrors() { return this.props.rawErrors ?? []; }
toJSON() {
return {
screenshotPath: this.props.screenshotPath,
domSnapshotPath: this.props.domSnapshotPath,
httpLog: this.props.httpLog,
rawErrors: this.props.rawErrors,
};
}
}
exports.Evidence = Evidence;

View File

@@ -0,0 +1,21 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.FindingStatus = void 0;
const ValueObject_1 = require("../../../../shared/domain/ValueObject");
class FindingStatus extends ValueObject_1.ValueObject {
static open() { return new FindingStatus({ value: 'open' }); }
static investigating() { return new FindingStatus({ value: 'investigating' }); }
static resolved() { return new FindingStatus({ value: 'resolved' }); }
static closed() { return new FindingStatus({ value: 'closed' }); }
static fromString(s) {
if (!FindingStatus.VALUES.includes(s)) {
throw new Error(`Invalid finding status: ${s}`);
}
return new FindingStatus({ value: s });
}
get value() { return this.props.value; }
isOpen() { return this.props.value === 'open'; }
isResolved() { return this.props.value === 'resolved'; }
}
exports.FindingStatus = FindingStatus;
FindingStatus.VALUES = ['open', 'investigating', 'resolved', 'closed'];

View File

@@ -0,0 +1,32 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.FindingType = void 0;
const ValueObject_1 = require("../../../../shared/domain/ValueObject");
class FindingType extends ValueObject_1.ValueObject {
static fromString(s) {
if (!FindingType.TYPES.includes(s)) {
throw new Error(`Invalid finding type: ${s}`);
}
return new FindingType({ value: s });
}
get value() { return this.props.value; }
}
exports.FindingType = FindingType;
FindingType.TYPES = [
'http_error',
'js_exception',
'console_error',
'navigation_fail',
'element_missing',
'timeout',
'validation_bypass',
'server_error_on_fuzz',
'xss_reflection',
'visual_regression',
'accessibility_violation',
'mobile_layout_issue',
'performance_degradation',
'offline_handling_missing',
'slow_network_no_feedback',
'external_service_crash',
];

View File

@@ -0,0 +1,19 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Severity = void 0;
const ValueObject_1 = require("../../../../shared/domain/ValueObject");
class Severity extends ValueObject_1.ValueObject {
static low() { return new Severity({ value: 'low' }); }
static medium() { return new Severity({ value: 'medium' }); }
static high() { return new Severity({ value: 'high' }); }
static critical() { return new Severity({ value: 'critical' }); }
static fromString(s) {
if (!Severity.LEVELS.includes(s)) {
throw new Error(`Invalid severity: ${s}`);
}
return new Severity({ value: s });
}
get value() { return this.props.value; }
}
exports.Severity = Severity;
Severity.LEVELS = ['low', 'medium', 'high', 'critical'];