api-tests-coverage 1.0.12 → 1.0.14
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/dist/dashboard/dist/assets/_basePickBy-CErN2e4K.js +1 -0
- package/dist/dashboard/dist/assets/_baseUniq-DzHorfx6.js +1 -0
- package/dist/dashboard/dist/assets/arc-g03p1JXB.js +1 -0
- package/dist/dashboard/dist/assets/architectureDiagram-VXUJARFQ-CLCqS7Lv.js +36 -0
- package/dist/dashboard/dist/assets/blockDiagram-VD42YOAC-V4vxrfzX.js +122 -0
- package/dist/dashboard/dist/assets/c4Diagram-YG6GDRKO-Bs4R4b6P.js +10 -0
- package/dist/dashboard/dist/assets/channel-BSnIwwuG.js +1 -0
- package/dist/dashboard/dist/assets/chunk-4BX2VUAB-oleArqPu.js +1 -0
- package/dist/dashboard/dist/assets/chunk-55IACEB6-BIFhHB94.js +1 -0
- package/dist/dashboard/dist/assets/chunk-B4BG7PRW-BChq1Wly.js +165 -0
- package/dist/dashboard/dist/assets/chunk-DI55MBZ5-D7eiRvhB.js +220 -0
- package/dist/dashboard/dist/assets/chunk-FMBD7UC4-BgEzYy_c.js +15 -0
- package/dist/dashboard/dist/assets/chunk-QN33PNHL-BNX7uRa_.js +1 -0
- package/dist/dashboard/dist/assets/chunk-QZHKN3VN-mq-zucvn.js +1 -0
- package/dist/dashboard/dist/assets/chunk-TZMSLE5B-DGTVcqTS.js +1 -0
- package/dist/dashboard/dist/assets/classDiagram-2ON5EDUG-Be0F7AG8.js +1 -0
- package/dist/dashboard/dist/assets/classDiagram-v2-WZHVMYZB-Be0F7AG8.js +1 -0
- package/dist/dashboard/dist/assets/clone-B5PF81Z3.js +1 -0
- package/dist/dashboard/dist/assets/cose-bilkent-S5V4N54A-xVw-THr_.js +1 -0
- package/dist/dashboard/dist/assets/dagre-6UL2VRFP-Bjadb8g_.js +4 -0
- package/dist/dashboard/dist/assets/diagram-PSM6KHXK-BPFtplp4.js +24 -0
- package/dist/dashboard/dist/assets/diagram-QEK2KX5R-CYxueP7U.js +43 -0
- package/dist/dashboard/dist/assets/diagram-S2PKOQOG-CRUXUQeh.js +24 -0
- package/dist/dashboard/dist/assets/erDiagram-Q2GNP2WA-DvI8ycM6.js +60 -0
- package/dist/dashboard/dist/assets/flowDiagram-NV44I4VS-BAHshMEg.js +162 -0
- package/dist/dashboard/dist/assets/ganttDiagram-JELNMOA3-BS4JnN-M.js +267 -0
- package/dist/dashboard/dist/assets/gitGraphDiagram-V2S2FVAM-Uz3nRdju.js +65 -0
- package/dist/dashboard/dist/assets/graph-Cwn7jgQS.js +1 -0
- package/dist/dashboard/dist/assets/index-D3_88Gr5.js +777 -0
- package/dist/dashboard/dist/assets/index-D_begBP0.css +1 -0
- package/dist/dashboard/dist/assets/infoDiagram-HS3SLOUP-HLwGZBHJ.js +2 -0
- package/dist/dashboard/dist/assets/journeyDiagram-XKPGCS4Q-CFgbI9OH.js +139 -0
- package/dist/dashboard/dist/assets/kanban-definition-3W4ZIXB7-D3u5Ov-5.js +89 -0
- package/dist/dashboard/dist/assets/layout-DgtRACDS.js +1 -0
- package/dist/dashboard/dist/assets/mindmap-definition-VGOIOE7T-BJ5xCmsL.js +68 -0
- package/dist/dashboard/dist/assets/pieDiagram-ADFJNKIX-BIOVbZG_.js +30 -0
- package/dist/dashboard/dist/assets/quadrantDiagram-AYHSOK5B-Crgu5WqK.js +7 -0
- package/dist/dashboard/dist/assets/requirementDiagram-UZGBJVZJ-ClNSNeYe.js +64 -0
- package/dist/dashboard/dist/assets/sankeyDiagram-TZEHDZUN-VcdyPlVE.js +10 -0
- package/dist/dashboard/dist/assets/sequenceDiagram-WL72ISMW-97qjzqIO.js +145 -0
- package/dist/dashboard/dist/assets/stateDiagram-FKZM4ZOC-BWqoDymf.js +1 -0
- package/dist/dashboard/dist/assets/stateDiagram-v2-4FDKWEC3-K_qkvHaB.js +1 -0
- package/dist/dashboard/dist/assets/timeline-definition-IT6M3QCI-DR6HNny6.js +61 -0
- package/dist/dashboard/dist/assets/treemap-GDKQZRPO-MpQr6tee.js +162 -0
- package/dist/dashboard/dist/assets/xychartDiagram-PRI3JC2R-bS40I4IT.js +7 -0
- package/dist/dashboard/dist/index.html +2 -2
- package/dist/src/ast/astAnalysisOrchestrator.d.ts +28 -0
- package/dist/src/ast/astAnalysisOrchestrator.d.ts.map +1 -1
- package/dist/src/ast/astAnalysisOrchestrator.js +97 -27
- package/dist/src/languages/javascript/httpInteractionExtractor.js +10 -4
- package/dist/src/pipeline/confidence.d.ts +70 -0
- package/dist/src/pipeline/confidence.d.ts.map +1 -0
- package/dist/src/pipeline/confidence.js +198 -0
- package/dist/src/pipeline/graph.d.ts +58 -0
- package/dist/src/pipeline/graph.d.ts.map +1 -0
- package/dist/src/pipeline/graph.js +199 -0
- package/dist/src/pipeline/index.d.ts +24 -0
- package/dist/src/pipeline/index.d.ts.map +1 -0
- package/dist/src/pipeline/index.js +41 -0
- package/dist/src/pipeline/orchestrator.d.ts +42 -0
- package/dist/src/pipeline/orchestrator.d.ts.map +1 -0
- package/dist/src/pipeline/orchestrator.js +115 -0
- package/dist/src/pipeline/stageInterface.d.ts +45 -0
- package/dist/src/pipeline/stageInterface.d.ts.map +1 -0
- package/dist/src/pipeline/stageInterface.js +17 -0
- package/dist/src/pipeline/stages/ast/abstractLayerTraversal.d.ts +38 -0
- package/dist/src/pipeline/stages/ast/abstractLayerTraversal.d.ts.map +1 -0
- package/dist/src/pipeline/stages/ast/abstractLayerTraversal.js +203 -0
- package/dist/src/pipeline/stages/ast/astStage.d.ts +19 -0
- package/dist/src/pipeline/stages/ast/astStage.d.ts.map +1 -0
- package/dist/src/pipeline/stages/ast/astStage.js +238 -0
- package/dist/src/pipeline/stages/ast/crossFileResolver.d.ts +23 -0
- package/dist/src/pipeline/stages/ast/crossFileResolver.d.ts.map +1 -0
- package/dist/src/pipeline/stages/ast/crossFileResolver.js +183 -0
- package/dist/src/pipeline/stages/ast/graphBuilder.d.ts +15 -0
- package/dist/src/pipeline/stages/ast/graphBuilder.d.ts.map +1 -0
- package/dist/src/pipeline/stages/ast/graphBuilder.js +268 -0
- package/dist/src/pipeline/stages/ast/importResolver.d.ts +22 -0
- package/dist/src/pipeline/stages/ast/importResolver.d.ts.map +1 -0
- package/dist/src/pipeline/stages/ast/importResolver.js +186 -0
- package/dist/src/pipeline/stages/ast/types.d.ts +85 -0
- package/dist/src/pipeline/stages/ast/types.d.ts.map +1 -0
- package/dist/src/pipeline/stages/ast/types.js +5 -0
- package/dist/src/pipeline/stages/dast/conflictEmitter.d.ts +25 -0
- package/dist/src/pipeline/stages/dast/conflictEmitter.d.ts.map +1 -0
- package/dist/src/pipeline/stages/dast/conflictEmitter.js +90 -0
- package/dist/src/pipeline/stages/dast/dastStage.d.ts +17 -0
- package/dist/src/pipeline/stages/dast/dastStage.d.ts.map +1 -0
- package/dist/src/pipeline/stages/dast/dastStage.js +203 -0
- package/dist/src/pipeline/stages/dast/types.d.ts +49 -0
- package/dist/src/pipeline/stages/dast/types.d.ts.map +1 -0
- package/dist/src/pipeline/stages/dast/types.js +9 -0
- package/dist/src/pipeline/stages/iast/iastStage.d.ts +17 -0
- package/dist/src/pipeline/stages/iast/iastStage.d.ts.map +1 -0
- package/dist/src/pipeline/stages/iast/iastStage.js +191 -0
- package/dist/src/pipeline/stages/iast/types.d.ts +48 -0
- package/dist/src/pipeline/stages/iast/types.d.ts.map +1 -0
- package/dist/src/pipeline/stages/iast/types.js +8 -0
- package/dist/src/pipeline/stages/merge/conflictDetector.d.ts +17 -0
- package/dist/src/pipeline/stages/merge/conflictDetector.d.ts.map +1 -0
- package/dist/src/pipeline/stages/merge/conflictDetector.js +60 -0
- package/dist/src/pipeline/stages/merge/coverageMappingBuilder.d.ts +15 -0
- package/dist/src/pipeline/stages/merge/coverageMappingBuilder.d.ts.map +1 -0
- package/dist/src/pipeline/stages/merge/coverageMappingBuilder.js +141 -0
- package/dist/src/pipeline/stages/merge/mergeRules.d.ts +39 -0
- package/dist/src/pipeline/stages/merge/mergeRules.d.ts.map +1 -0
- package/dist/src/pipeline/stages/merge/mergeRules.js +90 -0
- package/dist/src/pipeline/stages/merge/mergeStage.d.ts +20 -0
- package/dist/src/pipeline/stages/merge/mergeStage.d.ts.map +1 -0
- package/dist/src/pipeline/stages/merge/mergeStage.js +145 -0
- package/dist/src/pipeline/stages/merge/summaryComputer.d.ts +11 -0
- package/dist/src/pipeline/stages/merge/summaryComputer.d.ts.map +1 -0
- package/dist/src/pipeline/stages/merge/summaryComputer.js +46 -0
- package/dist/src/pipeline/stages/sca/ciDetector.d.ts +15 -0
- package/dist/src/pipeline/stages/sca/ciDetector.d.ts.map +1 -0
- package/dist/src/pipeline/stages/sca/ciDetector.js +87 -0
- package/dist/src/pipeline/stages/sca/dependencyClassification.d.ts +31 -0
- package/dist/src/pipeline/stages/sca/dependencyClassification.d.ts.map +1 -0
- package/dist/src/pipeline/stages/sca/dependencyClassification.js +296 -0
- package/dist/src/pipeline/stages/sca/dependencyDetector.d.ts +25 -0
- package/dist/src/pipeline/stages/sca/dependencyDetector.d.ts.map +1 -0
- package/dist/src/pipeline/stages/sca/dependencyDetector.js +416 -0
- package/dist/src/pipeline/stages/sca/scaStage.d.ts +21 -0
- package/dist/src/pipeline/stages/sca/scaStage.d.ts.map +1 -0
- package/dist/src/pipeline/stages/sca/scaStage.js +208 -0
- package/dist/src/pipeline/stages/sca/types.d.ts +61 -0
- package/dist/src/pipeline/stages/sca/types.d.ts.map +1 -0
- package/dist/src/pipeline/stages/sca/types.js +9 -0
- package/dist/src/pipeline/stages/tia/mockBoundaryDetector.d.ts +19 -0
- package/dist/src/pipeline/stages/tia/mockBoundaryDetector.d.ts.map +1 -0
- package/dist/src/pipeline/stages/tia/mockBoundaryDetector.js +118 -0
- package/dist/src/pipeline/stages/tia/parameterizedTestExpander.d.ts +20 -0
- package/dist/src/pipeline/stages/tia/parameterizedTestExpander.d.ts.map +1 -0
- package/dist/src/pipeline/stages/tia/parameterizedTestExpander.js +238 -0
- package/dist/src/pipeline/stages/tia/testEndpointMapper.d.ts +22 -0
- package/dist/src/pipeline/stages/tia/testEndpointMapper.d.ts.map +1 -0
- package/dist/src/pipeline/stages/tia/testEndpointMapper.js +134 -0
- package/dist/src/pipeline/stages/tia/testLayerClassifier.d.ts +16 -0
- package/dist/src/pipeline/stages/tia/testLayerClassifier.d.ts.map +1 -0
- package/dist/src/pipeline/stages/tia/testLayerClassifier.js +191 -0
- package/dist/src/pipeline/stages/tia/tiaStage.d.ts +20 -0
- package/dist/src/pipeline/stages/tia/tiaStage.d.ts.map +1 -0
- package/dist/src/pipeline/stages/tia/tiaStage.js +215 -0
- package/dist/src/pipeline/stages/tia/types.d.ts +52 -0
- package/dist/src/pipeline/stages/tia/types.d.ts.map +1 -0
- package/dist/src/pipeline/stages/tia/types.js +5 -0
- package/dist/src/pipeline/types.d.ts +128 -0
- package/dist/src/pipeline/types.d.ts.map +1 -0
- package/dist/src/pipeline/types.js +9 -0
- package/package.json +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"conflictDetector.d.ts","sourceRoot":"","sources":["../../../../../src/pipeline/stages/merge/conflictDetector.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,YAAY,EAA2B,MAAM,aAAa,CAAC;AACzE,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AAC1D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAEhD;;GAEG;AACH,wBAAgB,eAAe,CAC7B,KAAK,EAAE,sBAAsB,EAC7B,UAAU,EAAE,UAAU,GAAG,SAAS,EAClC,UAAU,EAAE,UAAU,GAAG,SAAS,GACjC,YAAY,EAAE,CA0ChB"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Conflict detector — detects stage disagreements and structural conflicts
|
|
4
|
+
* in the knowledge graph after all stages have run.
|
|
5
|
+
*
|
|
6
|
+
* Detects:
|
|
7
|
+
* - Runtime-unconfirmed: AST+TIA say covered, but IAST/DAST disagree
|
|
8
|
+
* - Stage disagreement: Two stages assign different types to the same node
|
|
9
|
+
*/
|
|
10
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
+
exports.detectConflicts = detectConflicts;
|
|
12
|
+
/**
|
|
13
|
+
* Detect conflicts across all stages.
|
|
14
|
+
*/
|
|
15
|
+
function detectConflicts(graph, iastOutput, dastOutput) {
|
|
16
|
+
var _a, _b, _c, _d, _e;
|
|
17
|
+
const conflicts = [];
|
|
18
|
+
// 1. Runtime-unconfirmed: endpoints that AST found but neither IAST nor DAST confirmed
|
|
19
|
+
const endpointNodes = graph.getNodesByType('endpoint');
|
|
20
|
+
const iastConfirmed = new Set((_a = iastOutput === null || iastOutput === void 0 ? void 0 : iastOutput.confirmedEndpoints) !== null && _a !== void 0 ? _a : []);
|
|
21
|
+
const dastConfirmed = new Set((_b = dastOutput === null || dastOutput === void 0 ? void 0 : dastOutput.confirmedEndpoints) !== null && _b !== void 0 ? _b : []);
|
|
22
|
+
const dastUnreachable = new Set((_c = dastOutput === null || dastOutput === void 0 ? void 0 : dastOutput.unreachableEndpoints) !== null && _c !== void 0 ? _c : []);
|
|
23
|
+
const hasRuntimeData = ((_d = iastOutput === null || iastOutput === void 0 ? void 0 : iastOutput.events.length) !== null && _d !== void 0 ? _d : 0) > 0 || ((_e = dastOutput === null || dastOutput === void 0 ? void 0 : dastOutput.results.length) !== null && _e !== void 0 ? _e : 0) > 0;
|
|
24
|
+
if (hasRuntimeData) {
|
|
25
|
+
for (const node of endpointNodes) {
|
|
26
|
+
// Only check endpoints from static stages (AST/TIA)
|
|
27
|
+
if (node.sourceStage !== 'ast' && node.sourceStage !== 'sca')
|
|
28
|
+
continue;
|
|
29
|
+
const confirmed = iastConfirmed.has(node.id) || dastConfirmed.has(node.id);
|
|
30
|
+
const unreachable = dastUnreachable.has(node.id);
|
|
31
|
+
if (!confirmed && !unreachable) {
|
|
32
|
+
conflicts.push({
|
|
33
|
+
conflictId: `conflict:runtime-unconfirmed:${node.id}`,
|
|
34
|
+
nodeId: node.id,
|
|
35
|
+
type: 'runtime-unconfirmed',
|
|
36
|
+
stages: getRuntimeStages(iastOutput, dastOutput),
|
|
37
|
+
stageOutputs: {
|
|
38
|
+
ast: 'endpoint-declared',
|
|
39
|
+
iast: iastConfirmed.has(node.id) ? 'confirmed' : 'not-observed',
|
|
40
|
+
dast: dastConfirmed.has(node.id) ? 'confirmed' : 'not-probed',
|
|
41
|
+
},
|
|
42
|
+
detail: `${node.label} was found by static analysis but not confirmed by any runtime stage.`,
|
|
43
|
+
suggestedAction: 'Check if the endpoint is covered by integration/e2e tests that produce IAST events or DAST probes.',
|
|
44
|
+
severity: 'info',
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
// 2. Stage disagreement: same node ID added by multiple stages with different types
|
|
50
|
+
// (This is handled by the graph merge(), which already returns ConflictNode[])
|
|
51
|
+
return conflicts;
|
|
52
|
+
}
|
|
53
|
+
function getRuntimeStages(iastOutput, dastOutput) {
|
|
54
|
+
const stages = ['ast'];
|
|
55
|
+
if (iastOutput && iastOutput.events.length > 0)
|
|
56
|
+
stages.push('iast');
|
|
57
|
+
if (dastOutput && dastOutput.results.length > 0)
|
|
58
|
+
stages.push('dast');
|
|
59
|
+
return stages;
|
|
60
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Coverage mapping builder — constructs `CoverageMapping` entries for every
|
|
3
|
+
* endpoint in the graph by walking its connected test files, assertions,
|
|
4
|
+
* mock boundaries, and runtime confirmations.
|
|
5
|
+
*/
|
|
6
|
+
import type { CoverageMapping } from '../../types';
|
|
7
|
+
import type { CoverageKnowledgeGraph } from '../../graph';
|
|
8
|
+
import type { TiaOutput } from '../tia/types';
|
|
9
|
+
import type { IastOutput } from '../iast/types';
|
|
10
|
+
import type { DastOutput } from '../dast/types';
|
|
11
|
+
/**
|
|
12
|
+
* Build coverage mappings for all endpoint-type nodes in the graph.
|
|
13
|
+
*/
|
|
14
|
+
export declare function buildCoverageMappings(graph: CoverageKnowledgeGraph, tiaOutput: TiaOutput | undefined, iastOutput: IastOutput | undefined, dastOutput: DastOutput | undefined, isStaticOnlyMode: boolean): CoverageMapping[];
|
|
15
|
+
//# sourceMappingURL=coverageMappingBuilder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"coverageMappingBuilder.d.ts","sourceRoot":"","sources":["../../../../../src/pipeline/stages/merge/coverageMappingBuilder.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EACV,eAAe,EAMhB,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AAC1D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAIhD;;GAEG;AACH,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,sBAAsB,EAC7B,SAAS,EAAE,SAAS,GAAG,SAAS,EAChC,UAAU,EAAE,UAAU,GAAG,SAAS,EAClC,UAAU,EAAE,UAAU,GAAG,SAAS,EAClC,gBAAgB,EAAE,OAAO,GACxB,eAAe,EAAE,CAuJnB"}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Coverage mapping builder — constructs `CoverageMapping` entries for every
|
|
4
|
+
* endpoint in the graph by walking its connected test files, assertions,
|
|
5
|
+
* mock boundaries, and runtime confirmations.
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.buildCoverageMappings = buildCoverageMappings;
|
|
9
|
+
const confidence_1 = require("../../confidence");
|
|
10
|
+
const mergeRules_1 = require("./mergeRules");
|
|
11
|
+
/**
|
|
12
|
+
* Build coverage mappings for all endpoint-type nodes in the graph.
|
|
13
|
+
*/
|
|
14
|
+
function buildCoverageMappings(graph, tiaOutput, iastOutput, dastOutput, isStaticOnlyMode) {
|
|
15
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
16
|
+
const mappings = [];
|
|
17
|
+
const endpointNodes = graph.getNodesByType('endpoint');
|
|
18
|
+
const iastConfirmed = new Set((_a = iastOutput === null || iastOutput === void 0 ? void 0 : iastOutput.confirmedEndpoints) !== null && _a !== void 0 ? _a : []);
|
|
19
|
+
const dastConfirmed = new Set((_b = dastOutput === null || dastOutput === void 0 ? void 0 : dastOutput.confirmedEndpoints) !== null && _b !== void 0 ? _b : []);
|
|
20
|
+
const dastUnreachable = new Set((_c = dastOutput === null || dastOutput === void 0 ? void 0 : dastOutput.unreachableEndpoints) !== null && _c !== void 0 ? _c : []);
|
|
21
|
+
// Build a lookup: endpointId → test classifications
|
|
22
|
+
const testLayerLookup = new Map();
|
|
23
|
+
if (tiaOutput) {
|
|
24
|
+
for (const classification of tiaOutput.classifications) {
|
|
25
|
+
testLayerLookup.set(classification.filePath, classification.layer);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
// Build a lookup: endpointId → mock boundary test files
|
|
29
|
+
const mockBoundaryLookup = new Map();
|
|
30
|
+
if (tiaOutput) {
|
|
31
|
+
for (const boundary of tiaOutput.mockBoundaries) {
|
|
32
|
+
if (!mockBoundaryLookup.has(boundary.testFilePath)) {
|
|
33
|
+
mockBoundaryLookup.set(boundary.testFilePath, new Set());
|
|
34
|
+
}
|
|
35
|
+
mockBoundaryLookup.get(boundary.testFilePath).add(boundary.mockedTarget);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
for (const endpoint of endpointNodes) {
|
|
39
|
+
// Find linked tests (incoming 'tests' and 'asserts' edges)
|
|
40
|
+
const incomingEdges = graph.getEdgesTo(endpoint.id);
|
|
41
|
+
const testEdges = incomingEdges.filter((e) => e.type === 'tests' || e.type === 'asserts');
|
|
42
|
+
const linkedTests = [];
|
|
43
|
+
const sourceStages = new Set([endpoint.sourceStage]);
|
|
44
|
+
let assertionConfirmed = false;
|
|
45
|
+
let assertionSource = 'unresolved';
|
|
46
|
+
let hasMockBoundary = false;
|
|
47
|
+
let bestTestLayer;
|
|
48
|
+
let urlResolution = 'literal';
|
|
49
|
+
let traversalDepth = 0;
|
|
50
|
+
for (const edge of testEdges) {
|
|
51
|
+
// Extract file path from source node ID (format: file:/path/to/test.ts)
|
|
52
|
+
const testFilePath = edge.sourceNodeId.replace(/^file:/, '');
|
|
53
|
+
if (!linkedTests.includes(testFilePath)) {
|
|
54
|
+
linkedTests.push(testFilePath);
|
|
55
|
+
}
|
|
56
|
+
sourceStages.add(edge.sourceStage);
|
|
57
|
+
// Check if this test has assertions
|
|
58
|
+
if (edge.type === 'asserts') {
|
|
59
|
+
assertionConfirmed = true;
|
|
60
|
+
assertionSource = 'direct';
|
|
61
|
+
}
|
|
62
|
+
// Check test layer
|
|
63
|
+
const layer = testLayerLookup.get(testFilePath);
|
|
64
|
+
if (layer) {
|
|
65
|
+
bestTestLayer = layer;
|
|
66
|
+
}
|
|
67
|
+
// Check for mock boundaries on this test file
|
|
68
|
+
if (mockBoundaryLookup.has(testFilePath)) {
|
|
69
|
+
hasMockBoundary = true;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
// Check for assertion nodes linked to this file
|
|
73
|
+
if (!assertionConfirmed) {
|
|
74
|
+
for (const testFile of linkedTests) {
|
|
75
|
+
const assertionNodeId = `assertion:${testFile}`;
|
|
76
|
+
if (graph.hasNode(assertionNodeId)) {
|
|
77
|
+
const assertionNode = graph.getNode(assertionNodeId);
|
|
78
|
+
if (assertionNode) {
|
|
79
|
+
assertionConfirmed = true;
|
|
80
|
+
assertionSource = (_e = (_d = assertionNode.metadata) === null || _d === void 0 ? void 0 : _d.assertionSource) !== null && _e !== void 0 ? _e : 'direct';
|
|
81
|
+
traversalDepth = (_g = (_f = assertionNode.metadata) === null || _f === void 0 ? void 0 : _f.traversalDepth) !== null && _g !== void 0 ? _g : 0;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
// Determine URL resolution type from endpoint metadata
|
|
87
|
+
const resolutionType = (_h = endpoint.metadata) === null || _h === void 0 ? void 0 : _h.resolutionType;
|
|
88
|
+
if (resolutionType === 'heuristic' || resolutionType === 'string-template' || resolutionType === 'interpolated-path') {
|
|
89
|
+
urlResolution = 'symbolic';
|
|
90
|
+
}
|
|
91
|
+
else if (resolutionType === 'direct' || resolutionType === 'constant' || resolutionType === 'enum') {
|
|
92
|
+
urlResolution = 'literal';
|
|
93
|
+
}
|
|
94
|
+
else if (!resolutionType) {
|
|
95
|
+
urlResolution = 'unresolved';
|
|
96
|
+
}
|
|
97
|
+
// Check mock boundaries on path
|
|
98
|
+
const pathNodeIds = [endpoint.id, ...linkedTests.map((t) => `file:${t}`)];
|
|
99
|
+
const mockBoundaryOnPath = hasMockBoundary;
|
|
100
|
+
// Build confidence evidence
|
|
101
|
+
const evidence = (0, confidence_1.buildConfidenceEvidence)(graph, pathNodeIds, isStaticOnlyMode);
|
|
102
|
+
// Compute confidence
|
|
103
|
+
const confidence = (0, confidence_1.computeConfidence)(evidence);
|
|
104
|
+
// Determine coverage class
|
|
105
|
+
const coverageClass = linkedTests.length > 0
|
|
106
|
+
? (0, mergeRules_1.determineCoverageClass)(bestTestLayer, mockBoundaryOnPath)
|
|
107
|
+
: 'uncovered';
|
|
108
|
+
// Check DAST reachability
|
|
109
|
+
const dastReachable = dastConfirmed.has(endpoint.id)
|
|
110
|
+
? true
|
|
111
|
+
: dastUnreachable.has(endpoint.id)
|
|
112
|
+
? false
|
|
113
|
+
: 'not-probed';
|
|
114
|
+
// Check runtime confirmation
|
|
115
|
+
const runtimeConfirmed = iastConfirmed.has(endpoint.id) || dastConfirmed.has(endpoint.id);
|
|
116
|
+
// Collect conflict IDs linked to this endpoint
|
|
117
|
+
const conflictEdges = graph.getEdgesTo(endpoint.id).filter((e) => e.type === 'conflicts-with');
|
|
118
|
+
const conflicts = conflictEdges.map((e) => e.sourceNodeId);
|
|
119
|
+
mappings.push({
|
|
120
|
+
itemId: endpoint.id,
|
|
121
|
+
itemType: 'endpoint',
|
|
122
|
+
linkedTests,
|
|
123
|
+
sourceStages: Array.from(sourceStages),
|
|
124
|
+
confidence,
|
|
125
|
+
coverageClass,
|
|
126
|
+
mockBoundaries: mockBoundaryOnPath
|
|
127
|
+
? linkedTests
|
|
128
|
+
.filter((t) => mockBoundaryLookup.has(t))
|
|
129
|
+
.flatMap((t) => Array.from(mockBoundaryLookup.get(t)))
|
|
130
|
+
: [],
|
|
131
|
+
assertionSource,
|
|
132
|
+
assertionConfirmed,
|
|
133
|
+
dastReachable,
|
|
134
|
+
runtimeConfirmed,
|
|
135
|
+
urlResolution,
|
|
136
|
+
conflicts,
|
|
137
|
+
traversalDepth,
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
return mappings;
|
|
141
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Merge rules — defines how graph nodes and edges from different stages
|
|
3
|
+
* are reconciled during the final merge stage.
|
|
4
|
+
*
|
|
5
|
+
* Core principle (RULE-09): A later stage may raise a node's confidence
|
|
6
|
+
* or enrich its test evidence, but MUST NOT demote it.
|
|
7
|
+
*/
|
|
8
|
+
import type { PipelineConfidence, CoverageClass, TestLayer, StageName } from '../../types';
|
|
9
|
+
/**
|
|
10
|
+
* RULE-09: Confidence can only be raised, never demoted.
|
|
11
|
+
*
|
|
12
|
+
* Returns the higher of two confidence levels.
|
|
13
|
+
*/
|
|
14
|
+
export declare function mergeConfidence(existing: PipelineConfidence, incoming: PipelineConfidence): PipelineConfidence;
|
|
15
|
+
/**
|
|
16
|
+
* Merge test evidence arrays (de-duplicate).
|
|
17
|
+
*/
|
|
18
|
+
export declare function mergeTestEvidence(existing: string[], incoming: string[]): string[];
|
|
19
|
+
/**
|
|
20
|
+
* Merge source stages (de-duplicate).
|
|
21
|
+
*/
|
|
22
|
+
export declare function mergeSourceStages(existing: StageName[], incoming: StageName[]): StageName[];
|
|
23
|
+
/**
|
|
24
|
+
* Determine coverage class from test layer and mock boundary presence.
|
|
25
|
+
*
|
|
26
|
+
* RULE-03: If a mock boundary exists on the path, the coverage class
|
|
27
|
+
* is 'mock-covered' regardless of the test layer.
|
|
28
|
+
*/
|
|
29
|
+
export declare function determineCoverageClass(testLayer: TestLayer | undefined, hasMockBoundary: boolean): CoverageClass;
|
|
30
|
+
/**
|
|
31
|
+
* Rank coverage classes for comparison (higher is better).
|
|
32
|
+
*/
|
|
33
|
+
export declare function coverageClassRank(cls: CoverageClass): number;
|
|
34
|
+
/**
|
|
35
|
+
* Merge two coverage classes — keep the highest rank.
|
|
36
|
+
* RULE-09: Never demote coverage class.
|
|
37
|
+
*/
|
|
38
|
+
export declare function mergeCoverageClass(existing: CoverageClass, incoming: CoverageClass): CoverageClass;
|
|
39
|
+
//# sourceMappingURL=mergeRules.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mergeRules.d.ts","sourceRoot":"","sources":["../../../../../src/pipeline/stages/merge/mergeRules.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,kBAAkB,EAAE,aAAa,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAE3F;;;;GAIG;AACH,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,kBAAkB,EAC5B,QAAQ,EAAE,kBAAkB,GAC3B,kBAAkB,CAKpB;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CAIlF;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,SAAS,EAAE,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,SAAS,EAAE,CAI3F;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CACpC,SAAS,EAAE,SAAS,GAAG,SAAS,EAChC,eAAe,EAAE,OAAO,GACvB,aAAa,CAef;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CAW5D;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,aAAa,EAAE,QAAQ,EAAE,aAAa,GAAG,aAAa,CAElG"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Merge rules — defines how graph nodes and edges from different stages
|
|
4
|
+
* are reconciled during the final merge stage.
|
|
5
|
+
*
|
|
6
|
+
* Core principle (RULE-09): A later stage may raise a node's confidence
|
|
7
|
+
* or enrich its test evidence, but MUST NOT demote it.
|
|
8
|
+
*/
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.mergeConfidence = mergeConfidence;
|
|
11
|
+
exports.mergeTestEvidence = mergeTestEvidence;
|
|
12
|
+
exports.mergeSourceStages = mergeSourceStages;
|
|
13
|
+
exports.determineCoverageClass = determineCoverageClass;
|
|
14
|
+
exports.coverageClassRank = coverageClassRank;
|
|
15
|
+
exports.mergeCoverageClass = mergeCoverageClass;
|
|
16
|
+
/**
|
|
17
|
+
* RULE-09: Confidence can only be raised, never demoted.
|
|
18
|
+
*
|
|
19
|
+
* Returns the higher of two confidence levels.
|
|
20
|
+
*/
|
|
21
|
+
function mergeConfidence(existing, incoming) {
|
|
22
|
+
const order = ['low', 'medium', 'high', 'verified'];
|
|
23
|
+
const existingIdx = order.indexOf(existing);
|
|
24
|
+
const incomingIdx = order.indexOf(incoming);
|
|
25
|
+
return existingIdx >= incomingIdx ? existing : incoming;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Merge test evidence arrays (de-duplicate).
|
|
29
|
+
*/
|
|
30
|
+
function mergeTestEvidence(existing, incoming) {
|
|
31
|
+
const set = new Set(existing);
|
|
32
|
+
for (const item of incoming)
|
|
33
|
+
set.add(item);
|
|
34
|
+
return Array.from(set);
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Merge source stages (de-duplicate).
|
|
38
|
+
*/
|
|
39
|
+
function mergeSourceStages(existing, incoming) {
|
|
40
|
+
const set = new Set(existing);
|
|
41
|
+
for (const item of incoming)
|
|
42
|
+
set.add(item);
|
|
43
|
+
return Array.from(set);
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Determine coverage class from test layer and mock boundary presence.
|
|
47
|
+
*
|
|
48
|
+
* RULE-03: If a mock boundary exists on the path, the coverage class
|
|
49
|
+
* is 'mock-covered' regardless of the test layer.
|
|
50
|
+
*/
|
|
51
|
+
function determineCoverageClass(testLayer, hasMockBoundary) {
|
|
52
|
+
var _a;
|
|
53
|
+
if (hasMockBoundary)
|
|
54
|
+
return 'mock-covered';
|
|
55
|
+
if (!testLayer)
|
|
56
|
+
return 'uncovered';
|
|
57
|
+
const layerToCoverageClass = {
|
|
58
|
+
unit: 'unit-covered',
|
|
59
|
+
component: 'component-covered',
|
|
60
|
+
integration: 'integration-covered',
|
|
61
|
+
api: 'api-covered',
|
|
62
|
+
e2e: 'e2e-covered',
|
|
63
|
+
performance: 'api-covered', // Performance tests are API-level coverage
|
|
64
|
+
security: 'api-covered', // Security tests are API-level coverage
|
|
65
|
+
};
|
|
66
|
+
return (_a = layerToCoverageClass[testLayer]) !== null && _a !== void 0 ? _a : 'uncovered';
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Rank coverage classes for comparison (higher is better).
|
|
70
|
+
*/
|
|
71
|
+
function coverageClassRank(cls) {
|
|
72
|
+
var _a;
|
|
73
|
+
const ranks = {
|
|
74
|
+
uncovered: 0,
|
|
75
|
+
'mock-covered': 1,
|
|
76
|
+
'unit-covered': 2,
|
|
77
|
+
'component-covered': 3,
|
|
78
|
+
'integration-covered': 4,
|
|
79
|
+
'api-covered': 5,
|
|
80
|
+
'e2e-covered': 6,
|
|
81
|
+
};
|
|
82
|
+
return (_a = ranks[cls]) !== null && _a !== void 0 ? _a : 0;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Merge two coverage classes — keep the highest rank.
|
|
86
|
+
* RULE-09: Never demote coverage class.
|
|
87
|
+
*/
|
|
88
|
+
function mergeCoverageClass(existing, incoming) {
|
|
89
|
+
return coverageClassRank(existing) >= coverageClassRank(incoming) ? existing : incoming;
|
|
90
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Merge Stage — Stage 6 (final) of the coverage pipeline.
|
|
3
|
+
*
|
|
4
|
+
* Responsibilities:
|
|
5
|
+
* 1. Run conflict detection across all stage outputs
|
|
6
|
+
* 2. Build coverage mappings for every endpoint
|
|
7
|
+
* 3. Compute the final pipeline summary
|
|
8
|
+
* 4. Produce the `PipelineOutput` with graph, sections, diagnostics, summary
|
|
9
|
+
*/
|
|
10
|
+
import type { PipelineStage, PipelineContext } from '../../stageInterface';
|
|
11
|
+
import type { PipelineOutput } from '../../types';
|
|
12
|
+
/**
|
|
13
|
+
* Output of the merge stage is the full `PipelineOutput`.
|
|
14
|
+
*/
|
|
15
|
+
export declare class MergeStage implements PipelineStage<PipelineOutput> {
|
|
16
|
+
readonly name: "merge";
|
|
17
|
+
readonly optional = false;
|
|
18
|
+
execute(context: PipelineContext): Promise<PipelineOutput>;
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=mergeStage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mergeStage.d.ts","sourceRoot":"","sources":["../../../../../src/pipeline/stages/merge/mergeStage.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAC3E,OAAO,KAAK,EAEV,cAAc,EAMf,MAAM,aAAa,CAAC;AAQrB;;GAEG;AACH,qBAAa,UAAW,YAAW,aAAa,CAAC,cAAc,CAAC;IAC9D,QAAQ,CAAC,IAAI,EAAG,OAAO,CAAU;IACjC,QAAQ,CAAC,QAAQ,SAAS;IAEpB,OAAO,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,cAAc,CAAC;CAmGjE"}
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Merge Stage — Stage 6 (final) of the coverage pipeline.
|
|
4
|
+
*
|
|
5
|
+
* Responsibilities:
|
|
6
|
+
* 1. Run conflict detection across all stage outputs
|
|
7
|
+
* 2. Build coverage mappings for every endpoint
|
|
8
|
+
* 3. Compute the final pipeline summary
|
|
9
|
+
* 4. Produce the `PipelineOutput` with graph, sections, diagnostics, summary
|
|
10
|
+
*/
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.MergeStage = void 0;
|
|
13
|
+
const conflictDetector_1 = require("./conflictDetector");
|
|
14
|
+
const coverageMappingBuilder_1 = require("./coverageMappingBuilder");
|
|
15
|
+
const summaryComputer_1 = require("./summaryComputer");
|
|
16
|
+
/**
|
|
17
|
+
* Output of the merge stage is the full `PipelineOutput`.
|
|
18
|
+
*/
|
|
19
|
+
class MergeStage {
|
|
20
|
+
constructor() {
|
|
21
|
+
this.name = 'merge';
|
|
22
|
+
this.optional = false;
|
|
23
|
+
}
|
|
24
|
+
async execute(context) {
|
|
25
|
+
var _a, _b;
|
|
26
|
+
const startTime = Date.now();
|
|
27
|
+
// Retrieve upstream stage outputs
|
|
28
|
+
const tiaOutput = context.stageOutputs.get('tia');
|
|
29
|
+
const iastOutput = context.stageOutputs.get('iast');
|
|
30
|
+
const dastOutput = context.stageOutputs.get('dast');
|
|
31
|
+
// Determine if we're in static-only mode (no IAST/DAST data)
|
|
32
|
+
const isStaticOnlyMode = ((_a = iastOutput === null || iastOutput === void 0 ? void 0 : iastOutput.events.length) !== null && _a !== void 0 ? _a : 0) === 0 && ((_b = dastOutput === null || dastOutput === void 0 ? void 0 : dastOutput.results.length) !== null && _b !== void 0 ? _b : 0) === 0;
|
|
33
|
+
// 1. Detect conflicts
|
|
34
|
+
const conflicts = (0, conflictDetector_1.detectConflicts)(context.graph, iastOutput, dastOutput);
|
|
35
|
+
// Add conflict nodes to graph
|
|
36
|
+
for (const conflict of conflicts) {
|
|
37
|
+
if (!context.graph.hasNode(conflict.conflictId)) {
|
|
38
|
+
const node = {
|
|
39
|
+
id: conflict.conflictId,
|
|
40
|
+
type: 'conflict',
|
|
41
|
+
label: `Conflict: ${conflict.type}`,
|
|
42
|
+
sourceStage: 'merge',
|
|
43
|
+
metadata: {
|
|
44
|
+
conflictType: conflict.type,
|
|
45
|
+
stages: conflict.stages,
|
|
46
|
+
detail: conflict.detail,
|
|
47
|
+
suggestedAction: conflict.suggestedAction,
|
|
48
|
+
severity: conflict.severity,
|
|
49
|
+
},
|
|
50
|
+
};
|
|
51
|
+
context.graph.addNode(node);
|
|
52
|
+
// Link to affected node
|
|
53
|
+
if (context.graph.hasNode(conflict.nodeId)) {
|
|
54
|
+
context.graph.addEdge({
|
|
55
|
+
id: `${conflict.conflictId}->conflicts-with->${conflict.nodeId}`,
|
|
56
|
+
type: 'conflicts-with',
|
|
57
|
+
sourceNodeId: conflict.conflictId,
|
|
58
|
+
targetNodeId: conflict.nodeId,
|
|
59
|
+
sourceStage: 'merge',
|
|
60
|
+
metadata: {},
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
// 2. Build coverage mappings
|
|
66
|
+
const allMappings = (0, coverageMappingBuilder_1.buildCoverageMappings)(context.graph, tiaOutput, iastOutput, dastOutput, isStaticOnlyMode);
|
|
67
|
+
// 3. Organize into sections
|
|
68
|
+
const sections = organizeSections(allMappings, context.graph);
|
|
69
|
+
// 4. Compute summary
|
|
70
|
+
const summary = (0, summaryComputer_1.computeSummary)(allMappings, tiaOutput);
|
|
71
|
+
// 5. Serialize graph
|
|
72
|
+
const graphSerialized = context.graph.toSerializable();
|
|
73
|
+
// 6. Collect diagnostics
|
|
74
|
+
const diagnosticsRecord = {};
|
|
75
|
+
for (const [stageName, diag] of context.diagnostics) {
|
|
76
|
+
diagnosticsRecord[stageName] = diag;
|
|
77
|
+
}
|
|
78
|
+
// Add merge diagnostics
|
|
79
|
+
const mergeDiagnostics = {
|
|
80
|
+
stageName: 'merge',
|
|
81
|
+
filesScanned: [],
|
|
82
|
+
filesSkipped: [],
|
|
83
|
+
durationMs: Date.now() - startTime,
|
|
84
|
+
metadata: {
|
|
85
|
+
totalMappings: allMappings.length,
|
|
86
|
+
conflictsDetected: conflicts.length,
|
|
87
|
+
isStaticOnlyMode,
|
|
88
|
+
graphNodeCount: graphSerialized.nodes.length,
|
|
89
|
+
graphEdgeCount: graphSerialized.edges.length,
|
|
90
|
+
},
|
|
91
|
+
};
|
|
92
|
+
context.diagnostics.set('merge', mergeDiagnostics);
|
|
93
|
+
diagnosticsRecord['merge'] = mergeDiagnostics;
|
|
94
|
+
// 7. Build final output
|
|
95
|
+
const output = {
|
|
96
|
+
graph: graphSerialized,
|
|
97
|
+
sections,
|
|
98
|
+
diagnostics: diagnosticsRecord,
|
|
99
|
+
summary,
|
|
100
|
+
};
|
|
101
|
+
context.stageOutputs.set('merge', output);
|
|
102
|
+
return output;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
exports.MergeStage = MergeStage;
|
|
106
|
+
/**
|
|
107
|
+
* Organize coverage mappings into the 6 output sections.
|
|
108
|
+
*/
|
|
109
|
+
function organizeSections(mappings, graph) {
|
|
110
|
+
const endpoints = [];
|
|
111
|
+
const parameters = [];
|
|
112
|
+
const integrationFlows = [];
|
|
113
|
+
const security = [];
|
|
114
|
+
const errorHandling = [];
|
|
115
|
+
const performance = [];
|
|
116
|
+
for (const mapping of mappings) {
|
|
117
|
+
switch (mapping.itemType) {
|
|
118
|
+
case 'endpoint':
|
|
119
|
+
endpoints.push(mapping);
|
|
120
|
+
break;
|
|
121
|
+
case 'service':
|
|
122
|
+
integrationFlows.push(mapping);
|
|
123
|
+
break;
|
|
124
|
+
case 'error-branch':
|
|
125
|
+
errorHandling.push(mapping);
|
|
126
|
+
break;
|
|
127
|
+
case 'security-path':
|
|
128
|
+
security.push(mapping);
|
|
129
|
+
break;
|
|
130
|
+
case 'validation-rule':
|
|
131
|
+
parameters.push(mapping);
|
|
132
|
+
break;
|
|
133
|
+
default:
|
|
134
|
+
endpoints.push(mapping);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
return {
|
|
138
|
+
endpoints,
|
|
139
|
+
parameters,
|
|
140
|
+
integrationFlows,
|
|
141
|
+
security,
|
|
142
|
+
errorHandling,
|
|
143
|
+
performance,
|
|
144
|
+
};
|
|
145
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Summary computer — computes the `PipelineSummary` from the final
|
|
3
|
+
* set of coverage mappings.
|
|
4
|
+
*/
|
|
5
|
+
import type { PipelineSummary, CoverageMapping } from '../../types';
|
|
6
|
+
import type { TiaOutput } from '../tia/types';
|
|
7
|
+
/**
|
|
8
|
+
* Compute the pipeline summary from coverage mappings.
|
|
9
|
+
*/
|
|
10
|
+
export declare function computeSummary(mappings: CoverageMapping[], tiaOutput: TiaOutput | undefined): PipelineSummary;
|
|
11
|
+
//# sourceMappingURL=summaryComputer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"summaryComputer.d.ts","sourceRoot":"","sources":["../../../../../src/pipeline/stages/merge/summaryComputer.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,eAAe,EAAa,MAAM,aAAa,CAAC;AAC/E,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAE9C;;GAEG;AACH,wBAAgB,cAAc,CAC5B,QAAQ,EAAE,eAAe,EAAE,EAC3B,SAAS,EAAE,SAAS,GAAG,SAAS,GAC/B,eAAe,CAwCjB"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Summary computer — computes the `PipelineSummary` from the final
|
|
4
|
+
* set of coverage mappings.
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.computeSummary = computeSummary;
|
|
8
|
+
/**
|
|
9
|
+
* Compute the pipeline summary from coverage mappings.
|
|
10
|
+
*/
|
|
11
|
+
function computeSummary(mappings, tiaOutput) {
|
|
12
|
+
var _a;
|
|
13
|
+
const endpointMappings = mappings.filter((m) => m.itemType === 'endpoint');
|
|
14
|
+
const totalEndpoints = endpointMappings.length;
|
|
15
|
+
const coveredEndpoints = endpointMappings.filter((m) => m.coverageClass !== 'uncovered').length;
|
|
16
|
+
const verifiedEndpoints = endpointMappings.filter((m) => m.confidence === 'verified').length;
|
|
17
|
+
const uncoveredEndpoints = endpointMappings.filter((m) => m.coverageClass === 'uncovered').length;
|
|
18
|
+
const mockLimitedPaths = endpointMappings.filter((m) => m.coverageClass === 'mock-covered').length;
|
|
19
|
+
const unresolvedAbstractions = endpointMappings.filter((m) => m.assertionSource === 'unresolved' && m.linkedTests.length > 0).length;
|
|
20
|
+
const conflictCount = endpointMappings.reduce((sum, m) => sum + m.conflicts.length, 0);
|
|
21
|
+
// Coverage by layer from TIA classifications
|
|
22
|
+
const coverageByLayer = {
|
|
23
|
+
unit: 0,
|
|
24
|
+
component: 0,
|
|
25
|
+
integration: 0,
|
|
26
|
+
api: 0,
|
|
27
|
+
e2e: 0,
|
|
28
|
+
performance: 0,
|
|
29
|
+
security: 0,
|
|
30
|
+
};
|
|
31
|
+
if (tiaOutput) {
|
|
32
|
+
for (const classification of tiaOutput.classifications) {
|
|
33
|
+
coverageByLayer[classification.layer] = ((_a = coverageByLayer[classification.layer]) !== null && _a !== void 0 ? _a : 0) + 1;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return {
|
|
37
|
+
totalEndpoints,
|
|
38
|
+
coveredEndpoints,
|
|
39
|
+
verifiedEndpoints,
|
|
40
|
+
uncoveredEndpoints,
|
|
41
|
+
mockLimitedPaths,
|
|
42
|
+
unresolvedAbstractions,
|
|
43
|
+
conflictCount,
|
|
44
|
+
coverageByLayer,
|
|
45
|
+
};
|
|
46
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CI platform detection.
|
|
3
|
+
*
|
|
4
|
+
* Detects the CI platform from project structure by checking
|
|
5
|
+
* for well-known CI configuration files.
|
|
6
|
+
*/
|
|
7
|
+
import type { CiPlatform } from './types';
|
|
8
|
+
/**
|
|
9
|
+
* Detect the CI platform from project structure.
|
|
10
|
+
*
|
|
11
|
+
* Returns the first matching platform, or 'none' if no CI configuration is found.
|
|
12
|
+
* Checks directories with `fs.existsSync` which handles both files and directories.
|
|
13
|
+
*/
|
|
14
|
+
export declare function detectCiPlatform(projectRoot: string): CiPlatform;
|
|
15
|
+
//# sourceMappingURL=ciDetector.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ciDetector.d.ts","sourceRoot":"","sources":["../../../../../src/pipeline/stages/sca/ciDetector.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAmC1C;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,WAAW,EAAE,MAAM,GAAG,UAAU,CAUhE"}
|