framework-mcp 1.1.1 → 1.1.3
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/CAPABILITY_TRANSFORMATION_SUMMARY.md +158 -0
- package/DAYS_5_6_COMPLETION_SUMMARY.md +178 -0
- package/DEPLOYMENT_SUMMARY_v1.1.3.md +211 -0
- package/README.md +102 -40
- package/RELEASE_NOTES_v1.1.3.md +321 -0
- package/dist/index.d.ts +27 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +675 -335
- package/dist/index.js.map +1 -1
- package/package.json +3 -2
- package/src/index.ts +820 -394
- package/test_capability_integration.js +73 -0
- package/test_comprehensive_scenarios.js +192 -0
- package/test_enhanced_detection.js +74 -0
- package/test_integrated_validation.js +112 -0
- package/test_language_update.js +101 -0
- package/test_live_validation.json +12 -0
- package/test_performance_monitoring.js +124 -0
- package/test_runner_automated.js +156 -0
- package/test_suite_comprehensive.js +218 -0
package/src/index.ts
CHANGED
|
@@ -30,30 +30,22 @@ interface VendorAnalysis {
|
|
|
30
30
|
vendor: string;
|
|
31
31
|
safeguardId: string;
|
|
32
32
|
safeguardTitle: string;
|
|
33
|
-
// Primary capability categorization
|
|
34
|
-
capability: 'full' | 'partial' | 'facilitates' | 'governance' | 'validates'
|
|
35
|
-
// Detailed breakdown
|
|
33
|
+
// Primary capability categorization - what role does this tool play?
|
|
34
|
+
capability: 'full' | 'partial' | 'facilitates' | 'governance' | 'validates';
|
|
35
|
+
// Detailed capability breakdown
|
|
36
36
|
capabilities: {
|
|
37
|
-
full: boolean; //
|
|
38
|
-
partial: boolean; //
|
|
39
|
-
facilitates: boolean; //
|
|
40
|
-
governance: boolean; //
|
|
41
|
-
validates: boolean; // Provides evidence
|
|
37
|
+
full: boolean; // Directly implements the core safeguard functionality
|
|
38
|
+
partial: boolean; // Implements limited aspects of the safeguard
|
|
39
|
+
facilitates: boolean; // Enhances or enables safeguard implementation by others
|
|
40
|
+
governance: boolean; // Provides policy, process, and oversight capabilities
|
|
41
|
+
validates: boolean; // Provides evidence, audit, and validation reporting
|
|
42
42
|
};
|
|
43
43
|
confidence: number;
|
|
44
44
|
reasoning: string;
|
|
45
45
|
evidence: string[];
|
|
46
|
-
//
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
subTaxonomicalElements: string[]; // Yellow elements addressed
|
|
50
|
-
governanceElements: string[]; // Orange elements addressed
|
|
51
|
-
implementationMethods: string[]; // Gray elements used
|
|
52
|
-
};
|
|
53
|
-
elementsNotCovered: {
|
|
54
|
-
coreRequirements: string[];
|
|
55
|
-
subTaxonomicalElements: string[];
|
|
56
|
-
};
|
|
46
|
+
// Capability-focused descriptions (replaces element coverage scoring)
|
|
47
|
+
toolCapabilityDescription: string; // What type of tool this is and its role
|
|
48
|
+
recommendedUse: string; // How practitioners should use this tool
|
|
57
49
|
}
|
|
58
50
|
|
|
59
51
|
interface AnalysisResult {
|
|
@@ -91,11 +83,16 @@ interface ValidationResult {
|
|
|
91
83
|
claimed_capability: string;
|
|
92
84
|
validation_status: 'SUPPORTED' | 'QUESTIONABLE' | 'UNSUPPORTED';
|
|
93
85
|
confidence_score: number; // 0-100
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
86
|
+
actual_capability_detected: string; // What capability the tool actually provides
|
|
87
|
+
capability_confidence: number; // Confidence in the detected capability
|
|
88
|
+
tool_capability_description: string; // Description of what type of tool this is
|
|
89
|
+
recommended_use: string; // How practitioners should use this tool
|
|
90
|
+
domain_validation: {
|
|
91
|
+
required_tool_type: string;
|
|
92
|
+
detected_tool_type: string;
|
|
93
|
+
domain_match: boolean;
|
|
94
|
+
capability_adjusted: boolean;
|
|
95
|
+
original_claim?: string;
|
|
99
96
|
};
|
|
100
97
|
gaps_identified: string[];
|
|
101
98
|
strengths_identified: string[];
|
|
@@ -103,6 +100,39 @@ interface ValidationResult {
|
|
|
103
100
|
detailed_feedback: string;
|
|
104
101
|
}
|
|
105
102
|
|
|
103
|
+
// Domain-specific validation mapping
|
|
104
|
+
const SAFEGUARD_DOMAIN_REQUIREMENTS: Record<string, {
|
|
105
|
+
domain: string;
|
|
106
|
+
required_tool_types: string[];
|
|
107
|
+
description: string;
|
|
108
|
+
}> = {
|
|
109
|
+
"1.1": {
|
|
110
|
+
domain: "Asset Inventory",
|
|
111
|
+
required_tool_types: ["inventory", "asset_management", "cmdb", "discovery"],
|
|
112
|
+
description: "Only asset inventory and discovery tools can provide FULL/PARTIAL implementation capability"
|
|
113
|
+
},
|
|
114
|
+
"1.2": {
|
|
115
|
+
domain: "Asset Management",
|
|
116
|
+
required_tool_types: ["inventory", "asset_management", "network_security", "nac"],
|
|
117
|
+
description: "Asset management or network access control tools required for FULL/PARTIAL implementation capability"
|
|
118
|
+
},
|
|
119
|
+
"5.1": {
|
|
120
|
+
domain: "Account Management",
|
|
121
|
+
required_tool_types: ["identity_management", "iam", "directory", "account_management"],
|
|
122
|
+
description: "Identity and account management tools required for FULL/PARTIAL implementation capability"
|
|
123
|
+
},
|
|
124
|
+
"6.3": {
|
|
125
|
+
domain: "Authentication",
|
|
126
|
+
required_tool_types: ["mfa", "authentication", "identity_management", "iam"],
|
|
127
|
+
description: "Multi-factor authentication and identity tools required for FULL/PARTIAL implementation capability"
|
|
128
|
+
},
|
|
129
|
+
"7.1": {
|
|
130
|
+
domain: "Vulnerability Management",
|
|
131
|
+
required_tool_types: ["vulnerability_management", "vulnerability_scanner", "patch_management"],
|
|
132
|
+
description: "Vulnerability management and scanning tools required for FULL/PARTIAL implementation capability"
|
|
133
|
+
}
|
|
134
|
+
};
|
|
135
|
+
|
|
106
136
|
// Enhanced CIS Controls Framework Data with color-coded categorization
|
|
107
137
|
const CIS_SAFEGUARDS: Record<string, SafeguardElement> = {
|
|
108
138
|
"1.1": {
|
|
@@ -5560,7 +5590,7 @@ export class GRCAnalysisServer {
|
|
|
5560
5590
|
tools: [
|
|
5561
5591
|
{
|
|
5562
5592
|
name: 'analyze_vendor_response',
|
|
5563
|
-
description: 'Analyze a vendor response
|
|
5593
|
+
description: 'Analyze a vendor response to determine their tool capability role (Full Implementation, Partial Implementation, Facilitates, Governance, or Validates) for a specific CIS Control safeguard',
|
|
5564
5594
|
inputSchema: {
|
|
5565
5595
|
type: 'object',
|
|
5566
5596
|
properties: {
|
|
@@ -5575,7 +5605,7 @@ export class GRCAnalysisServer {
|
|
|
5575
5605
|
},
|
|
5576
5606
|
response_text: {
|
|
5577
5607
|
type: 'string',
|
|
5578
|
-
description: 'Vendor response text
|
|
5608
|
+
description: 'Vendor response text describing their tool capabilities for the safeguard'
|
|
5579
5609
|
}
|
|
5580
5610
|
},
|
|
5581
5611
|
required: ['vendor_name', 'safeguard_id', 'response_text']
|
|
@@ -5603,7 +5633,7 @@ export class GRCAnalysisServer {
|
|
|
5603
5633
|
} as Tool,
|
|
5604
5634
|
{
|
|
5605
5635
|
name: 'validate_coverage_claim',
|
|
5606
|
-
description: 'Validate a vendor\'s
|
|
5636
|
+
description: 'Validate a vendor\'s implementation capability claim (FULL/PARTIAL) against specific safeguard requirements and evidence quality',
|
|
5607
5637
|
inputSchema: {
|
|
5608
5638
|
type: 'object',
|
|
5609
5639
|
properties: {
|
|
@@ -5619,16 +5649,16 @@ export class GRCAnalysisServer {
|
|
|
5619
5649
|
coverage_claim: {
|
|
5620
5650
|
type: 'string',
|
|
5621
5651
|
enum: ['FULL', 'PARTIAL'],
|
|
5622
|
-
description: 'Vendor\'s
|
|
5652
|
+
description: 'Vendor\'s implementation capability claim (FULL = complete implementation, PARTIAL = limited scope implementation)'
|
|
5623
5653
|
},
|
|
5624
5654
|
response_text: {
|
|
5625
5655
|
type: 'string',
|
|
5626
|
-
description: 'Vendor response explaining their
|
|
5656
|
+
description: 'Vendor response explaining their implementation capabilities'
|
|
5627
5657
|
},
|
|
5628
5658
|
capabilities: {
|
|
5629
5659
|
type: 'array',
|
|
5630
5660
|
items: { type: 'string' },
|
|
5631
|
-
description: 'List of vendor
|
|
5661
|
+
description: 'List of additional vendor capability types (Governance, Facilitates, Validates)'
|
|
5632
5662
|
}
|
|
5633
5663
|
},
|
|
5634
5664
|
required: ['vendor_name', 'safeguard_id', 'coverage_claim', 'response_text', 'capabilities']
|
|
@@ -5655,7 +5685,7 @@ export class GRCAnalysisServer {
|
|
|
5655
5685
|
} as Tool,
|
|
5656
5686
|
{
|
|
5657
5687
|
name: 'validate_vendor_mapping',
|
|
5658
|
-
description: 'Validate whether a vendor\'s
|
|
5688
|
+
description: 'Validate whether a vendor\'s claimed capability role (Full Implementation/Partial Implementation/Facilitates/Governance/Validates) is actually supported by their supporting evidence for a specific CIS safeguard',
|
|
5659
5689
|
inputSchema: {
|
|
5660
5690
|
type: 'object',
|
|
5661
5691
|
properties: {
|
|
@@ -5672,11 +5702,11 @@ export class GRCAnalysisServer {
|
|
|
5672
5702
|
claimed_capability: {
|
|
5673
5703
|
type: 'string',
|
|
5674
5704
|
enum: ['full', 'partial', 'facilitates', 'governance', 'validates'],
|
|
5675
|
-
description: 'Vendor\'s claimed capability
|
|
5705
|
+
description: 'Vendor\'s claimed capability role: full (complete implementation), partial (limited implementation), facilitates (enables/enhances), governance (policies/processes), validates (evidence/reporting)'
|
|
5676
5706
|
},
|
|
5677
5707
|
supporting_text: {
|
|
5678
5708
|
type: 'string',
|
|
5679
|
-
description: 'Vendor\'s supporting
|
|
5709
|
+
description: 'Vendor\'s supporting evidence explaining how their tool fulfills the claimed capability role'
|
|
5680
5710
|
}
|
|
5681
5711
|
},
|
|
5682
5712
|
required: ['safeguard_id', 'claimed_capability', 'supporting_text']
|
|
@@ -5687,28 +5717,49 @@ export class GRCAnalysisServer {
|
|
|
5687
5717
|
|
|
5688
5718
|
this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
5689
5719
|
const { name, arguments: args } = request.params;
|
|
5720
|
+
const startTime = Date.now();
|
|
5690
5721
|
|
|
5691
5722
|
try {
|
|
5723
|
+
let result;
|
|
5692
5724
|
switch (name) {
|
|
5693
5725
|
case 'analyze_vendor_response':
|
|
5694
|
-
|
|
5726
|
+
result = await this.analyzeVendorResponse(args);
|
|
5727
|
+
break;
|
|
5695
5728
|
case 'get_safeguard_details':
|
|
5696
|
-
|
|
5729
|
+
result = await this.getSafeguardDetails(args);
|
|
5730
|
+
break;
|
|
5697
5731
|
case 'validate_coverage_claim':
|
|
5698
|
-
|
|
5732
|
+
result = await this.validateCoverageClaim(args);
|
|
5733
|
+
break;
|
|
5699
5734
|
case 'list_available_safeguards':
|
|
5700
|
-
|
|
5735
|
+
result = await this.listAvailableSafeguards(args);
|
|
5736
|
+
break;
|
|
5701
5737
|
case 'validate_vendor_mapping':
|
|
5702
|
-
|
|
5738
|
+
result = await this.validateVendorMapping(args);
|
|
5739
|
+
break;
|
|
5703
5740
|
default:
|
|
5704
5741
|
throw new Error(`Unknown tool: ${name}`);
|
|
5705
5742
|
}
|
|
5743
|
+
|
|
5744
|
+
// Record successful execution time
|
|
5745
|
+
const executionTime = Date.now() - startTime;
|
|
5746
|
+
this.recordToolExecution(name, executionTime);
|
|
5747
|
+
|
|
5748
|
+
return result;
|
|
5706
5749
|
} catch (error) {
|
|
5750
|
+
// Record error and performance metrics
|
|
5751
|
+
this.performanceMetrics.errorCount++;
|
|
5752
|
+
const executionTime = Date.now() - startTime;
|
|
5753
|
+
this.recordToolExecution(`${name}_error`, executionTime);
|
|
5754
|
+
|
|
5755
|
+
const errorMessage = this.formatErrorMessage(error, name);
|
|
5756
|
+
console.error(`[FrameworkMCP] Tool execution error: ${name}`, error);
|
|
5757
|
+
|
|
5707
5758
|
return {
|
|
5708
5759
|
content: [
|
|
5709
5760
|
{
|
|
5710
5761
|
type: 'text',
|
|
5711
|
-
text:
|
|
5762
|
+
text: errorMessage,
|
|
5712
5763
|
},
|
|
5713
5764
|
],
|
|
5714
5765
|
};
|
|
@@ -5719,10 +5770,16 @@ export class GRCAnalysisServer {
|
|
|
5719
5770
|
private async getSafeguardDetails(args: any) {
|
|
5720
5771
|
const { safeguard_id, include_examples = true } = args;
|
|
5721
5772
|
|
|
5722
|
-
|
|
5723
|
-
|
|
5724
|
-
|
|
5773
|
+
// Input validation
|
|
5774
|
+
this.validateSafeguardId(safeguard_id);
|
|
5775
|
+
|
|
5776
|
+
// Check cache first
|
|
5777
|
+
const cached = this.getCachedSafeguardDetails(safeguard_id, include_examples);
|
|
5778
|
+
if (cached) {
|
|
5779
|
+
return cached;
|
|
5725
5780
|
}
|
|
5781
|
+
|
|
5782
|
+
const safeguard = CIS_SAFEGUARDS[safeguard_id];
|
|
5726
5783
|
|
|
5727
5784
|
const result = {
|
|
5728
5785
|
...safeguard,
|
|
@@ -5752,7 +5809,7 @@ export class GRCAnalysisServer {
|
|
|
5752
5809
|
}
|
|
5753
5810
|
};
|
|
5754
5811
|
|
|
5755
|
-
|
|
5812
|
+
const response = {
|
|
5756
5813
|
content: [
|
|
5757
5814
|
{
|
|
5758
5815
|
type: 'text',
|
|
@@ -5760,11 +5817,24 @@ export class GRCAnalysisServer {
|
|
|
5760
5817
|
},
|
|
5761
5818
|
],
|
|
5762
5819
|
};
|
|
5820
|
+
|
|
5821
|
+
// Cache the result for future requests
|
|
5822
|
+
this.setCachedSafeguardDetails(safeguard_id, include_examples, response);
|
|
5823
|
+
|
|
5824
|
+
return response;
|
|
5763
5825
|
}
|
|
5764
5826
|
|
|
5765
5827
|
private async listAvailableSafeguards(args: any) {
|
|
5766
5828
|
const { implementation_group, security_function } = args;
|
|
5767
5829
|
|
|
5830
|
+
// Check cache for complete safeguard list (only if no filters applied)
|
|
5831
|
+
if (!implementation_group && !security_function && this.cache.safeguardList) {
|
|
5832
|
+
const cacheAge = Date.now() - this.cache.safeguardList.timestamp;
|
|
5833
|
+
if (cacheAge < 10 * 60 * 1000) { // 10 minute cache for safeguard list
|
|
5834
|
+
return this.cache.safeguardList.data;
|
|
5835
|
+
}
|
|
5836
|
+
}
|
|
5837
|
+
|
|
5768
5838
|
let safeguards = Object.values(CIS_SAFEGUARDS);
|
|
5769
5839
|
|
|
5770
5840
|
if (implementation_group) {
|
|
@@ -5791,7 +5861,7 @@ export class GRCAnalysisServer {
|
|
|
5791
5861
|
}))
|
|
5792
5862
|
};
|
|
5793
5863
|
|
|
5794
|
-
|
|
5864
|
+
const response = {
|
|
5795
5865
|
content: [
|
|
5796
5866
|
{
|
|
5797
5867
|
type: 'text',
|
|
@@ -5799,17 +5869,32 @@ export class GRCAnalysisServer {
|
|
|
5799
5869
|
},
|
|
5800
5870
|
],
|
|
5801
5871
|
};
|
|
5872
|
+
|
|
5873
|
+
// Cache the complete list if no filters were applied
|
|
5874
|
+
if (!implementation_group && !security_function) {
|
|
5875
|
+
this.cache.safeguardList = {
|
|
5876
|
+
data: response,
|
|
5877
|
+
timestamp: Date.now()
|
|
5878
|
+
};
|
|
5879
|
+
}
|
|
5880
|
+
|
|
5881
|
+
return response;
|
|
5802
5882
|
}
|
|
5803
5883
|
|
|
5804
5884
|
private async analyzeVendorResponse(args: any) {
|
|
5805
5885
|
const { vendor_name, safeguard_id, response_text } = args;
|
|
5806
5886
|
|
|
5807
|
-
|
|
5808
|
-
|
|
5809
|
-
|
|
5887
|
+
// Input validation
|
|
5888
|
+
this.validateSafeguardId(safeguard_id);
|
|
5889
|
+
this.validateTextInput(response_text, 'Response text');
|
|
5890
|
+
|
|
5891
|
+
if (!vendor_name || typeof vendor_name !== 'string' || vendor_name.trim().length === 0) {
|
|
5892
|
+
throw new Error('Vendor name is required');
|
|
5810
5893
|
}
|
|
5811
5894
|
|
|
5812
|
-
const
|
|
5895
|
+
const safeguard = CIS_SAFEGUARDS[safeguard_id];
|
|
5896
|
+
|
|
5897
|
+
const analysis = this.performCapabilityAnalysis(vendor_name, safeguard, response_text);
|
|
5813
5898
|
|
|
5814
5899
|
return {
|
|
5815
5900
|
content: [
|
|
@@ -5829,7 +5914,7 @@ export class GRCAnalysisServer {
|
|
|
5829
5914
|
throw new Error(`Safeguard ${safeguard_id} not found`);
|
|
5830
5915
|
}
|
|
5831
5916
|
|
|
5832
|
-
const analysis = this.
|
|
5917
|
+
const analysis = this.performCapabilityAnalysis(vendor_name, safeguard, response_text);
|
|
5833
5918
|
|
|
5834
5919
|
// Validate the coverage claim
|
|
5835
5920
|
const validation = this.validateClaim(coverage_claim, analysis, capabilities, safeguard);
|
|
@@ -5851,182 +5936,284 @@ export class GRCAnalysisServer {
|
|
|
5851
5936
|
};
|
|
5852
5937
|
}
|
|
5853
5938
|
|
|
5854
|
-
private
|
|
5939
|
+
private performCapabilityAnalysis(vendorName: string, safeguard: SafeguardElement, responseText: string): VendorAnalysis {
|
|
5855
5940
|
const text = responseText.toLowerCase();
|
|
5856
5941
|
|
|
5857
|
-
//
|
|
5858
|
-
const
|
|
5942
|
+
// Step 1: Determine what type of capability this tool is claiming
|
|
5943
|
+
const claimedCapability = this.determineClaimedCapability(text, safeguard);
|
|
5944
|
+
|
|
5945
|
+
// Step 2: Assess how well the tool executes that specific capability type
|
|
5946
|
+
const qualityAssessment = this.assessCapabilityQuality(text, safeguard, claimedCapability);
|
|
5947
|
+
|
|
5948
|
+
// Step 3: Generate capability-focused analysis
|
|
5949
|
+
return this.generateCapabilityAnalysis(vendorName, safeguard, responseText, claimedCapability, qualityAssessment);
|
|
5950
|
+
}
|
|
5951
|
+
|
|
5952
|
+
private determineClaimedCapability(text: string, safeguard: SafeguardElement): 'full' | 'partial' | 'facilitates' | 'governance' | 'validates' {
|
|
5953
|
+
// Capability detection keywords - focused on what the tool DOES, not what elements it covers
|
|
5954
|
+
const governanceIndicators = [
|
|
5859
5955
|
'policy', 'policies', 'manage', 'process', 'workflow', 'governance', 'grc',
|
|
5860
5956
|
'compliance management', 'documented', 'establish', 'maintain', 'procedure',
|
|
5861
5957
|
'control', 'controls', 'framework', 'standard', 'enterprise risk management',
|
|
5862
5958
|
'centralized management', 'oversight'
|
|
5863
5959
|
];
|
|
5864
5960
|
|
|
5865
|
-
const
|
|
5866
|
-
// Technical facilitation (original keywords)
|
|
5961
|
+
const facilitatesIndicators = [
|
|
5867
5962
|
'improve', 'enhance', 'optimize', 'faster', 'better', 'stronger', 'automate',
|
|
5868
5963
|
'streamline', 'efficiency', 'facilitate', 'support', 'enable', 'accelerate',
|
|
5869
5964
|
'api', 'integration', 'data', 'export', 'import', 'sync', 'feed',
|
|
5870
|
-
// Data provision and enrichment
|
|
5871
5965
|
'provides data', 'data source', 'data feeds', 'enrichment', 'data enrichment',
|
|
5872
5966
|
'supplemental data', 'additional data', 'contextual data', 'threat data',
|
|
5873
5967
|
'intelligence feeds', 'data aggregation', 'data collection', 'data gathering',
|
|
5874
5968
|
'feeds data', 'populates', 'informs', 'enriches', 'supplements',
|
|
5875
|
-
// Governance/process facilitation (new keywords for tools like Upolicy)
|
|
5876
5969
|
'enables compliance', 'facilitates implementation', 'supports compliance',
|
|
5877
5970
|
'creates framework', 'enables organizations', 'infrastructure', 'foundation',
|
|
5878
|
-
'compliance infrastructure', 'audit infrastructure', 'policy framework',
|
|
5879
|
-
'enables effective', 'working together', 'comprehensive coverage',
|
|
5880
5971
|
'template', 'templates', 'workflow automation', 'orchestration'
|
|
5881
5972
|
];
|
|
5882
5973
|
|
|
5883
|
-
const
|
|
5974
|
+
const validatesIndicators = [
|
|
5884
5975
|
'audit', 'report', 'evidence', 'verify', 'validate', 'check', 'monitor',
|
|
5885
5976
|
'compliance', 'compliance report', 'assessment', 'logging', 'tracking', 'review', 'attest',
|
|
5886
5977
|
'dashboard', 'metrics', 'analytics', 'visibility', 'alert', 'attestation',
|
|
5887
5978
|
'compliance tracking', 'audit trail', 'reporting capabilities', 'audit capabilities'
|
|
5888
5979
|
];
|
|
5889
5980
|
|
|
5890
|
-
//
|
|
5891
|
-
const
|
|
5892
|
-
|
|
5893
|
-
|
|
5894
|
-
const
|
|
5981
|
+
// Direct implementation indicators (tools that actually perform the safeguard)
|
|
5982
|
+
const implementationIndicators = this.getImplementationIndicators(safeguard.id);
|
|
5983
|
+
|
|
5984
|
+
// Calculate keyword presence scores
|
|
5985
|
+
const governanceScore = this.calculateKeywordScore(text, governanceIndicators);
|
|
5986
|
+
const facilitatesScore = this.calculateKeywordScore(text, facilitatesIndicators);
|
|
5987
|
+
const validatesScore = this.calculateKeywordScore(text, validatesIndicators);
|
|
5988
|
+
const implementationScore = this.calculateKeywordScore(text, implementationIndicators);
|
|
5989
|
+
|
|
5990
|
+
// Determine claimed capability based on strongest indicators and patterns
|
|
5991
|
+
if (implementationScore > 0.2 && implementationScore >= Math.max(facilitatesScore, governanceScore, validatesScore)) {
|
|
5992
|
+
// Tool claims to directly implement the safeguard
|
|
5993
|
+
return implementationScore > 0.5 ? 'full' : 'partial';
|
|
5994
|
+
} else if (governanceScore > 0.2 && governanceScore >= Math.max(facilitatesScore, validatesScore)) {
|
|
5995
|
+
return 'governance';
|
|
5996
|
+
} else if (validatesScore > 0.2 && validatesScore >= facilitatesScore) {
|
|
5997
|
+
return 'validates';
|
|
5998
|
+
} else {
|
|
5999
|
+
return 'facilitates';
|
|
6000
|
+
}
|
|
6001
|
+
}
|
|
5895
6002
|
|
|
5896
|
-
|
|
5897
|
-
|
|
5898
|
-
const
|
|
5899
|
-
|
|
6003
|
+
private getImplementationIndicators(safeguardId: string): string[] {
|
|
6004
|
+
// Return specific indicators for what constitutes direct implementation for each safeguard
|
|
6005
|
+
const implementationMap: Record<string, string[]> = {
|
|
6006
|
+
"1.1": ['inventory', 'discovery', 'asset management', 'catalog', 'enumerate', 'scan devices', 'device database'],
|
|
6007
|
+
"1.2": ['unauthorized', 'rogue', 'detect', 'identify unauthorized', 'quarantine', 'block unauthorized'],
|
|
6008
|
+
"5.1": ['account inventory', 'user management', 'identity management', 'account lifecycle', 'user provisioning'],
|
|
6009
|
+
"6.3": ['multi-factor', 'mfa', '2fa', 'authentication', 'two-factor', 'multi-factor authentication'],
|
|
6010
|
+
"7.1": ['vulnerability', 'vuln', 'scanning', 'vulnerability management', 'security testing', 'penetration testing']
|
|
6011
|
+
};
|
|
5900
6012
|
|
|
5901
|
-
|
|
5902
|
-
|
|
5903
|
-
|
|
6013
|
+
return implementationMap[safeguardId] || [];
|
|
6014
|
+
}
|
|
6015
|
+
|
|
6016
|
+
private assessCapabilityQuality(text: string, safeguard: SafeguardElement, claimedCapability: string): {
|
|
6017
|
+
quality: 'excellent' | 'good' | 'fair' | 'poor',
|
|
6018
|
+
confidence: number,
|
|
6019
|
+
evidence: string[],
|
|
6020
|
+
gaps: string[]
|
|
6021
|
+
} {
|
|
6022
|
+
// Assess how well the tool executes the claimed capability type
|
|
6023
|
+
const evidence: string[] = [];
|
|
6024
|
+
const gaps: string[] = [];
|
|
5904
6025
|
|
|
5905
|
-
//
|
|
5906
|
-
|
|
5907
|
-
'enables compliance', 'facilitates implementation', 'creates framework',
|
|
5908
|
-
'policy framework', 'compliance infrastructure', 'audit infrastructure',
|
|
5909
|
-
'enables organizations', 'enables effective', 'working together',
|
|
5910
|
-
'creates the policy framework', 'enables organizations to implement',
|
|
5911
|
-
'facilitates implementation of', 'compliance infrastructure facilitates'
|
|
5912
|
-
];
|
|
5913
|
-
const hasFacilitationPattern = facilitationPatterns.some(pattern => text.includes(pattern));
|
|
6026
|
+
// Quality assessment based on capability type
|
|
6027
|
+
let qualityScore = 0;
|
|
5914
6028
|
|
|
5915
|
-
|
|
5916
|
-
|
|
5917
|
-
|
|
5918
|
-
|
|
5919
|
-
|
|
5920
|
-
|
|
5921
|
-
|
|
6029
|
+
switch (claimedCapability) {
|
|
6030
|
+
case 'full':
|
|
6031
|
+
case 'partial':
|
|
6032
|
+
qualityScore = this.assessImplementationQuality(text, safeguard, evidence, gaps);
|
|
6033
|
+
break;
|
|
6034
|
+
case 'governance':
|
|
6035
|
+
qualityScore = this.assessGovernanceQuality(text, safeguard, evidence, gaps);
|
|
6036
|
+
break;
|
|
6037
|
+
case 'facilitates':
|
|
6038
|
+
qualityScore = this.assessFacilitationQuality(text, safeguard, evidence, gaps);
|
|
6039
|
+
break;
|
|
6040
|
+
case 'validates':
|
|
6041
|
+
qualityScore = this.assessValidationQuality(text, safeguard, evidence, gaps);
|
|
6042
|
+
break;
|
|
6043
|
+
}
|
|
6044
|
+
|
|
6045
|
+
// Convert score to quality rating
|
|
6046
|
+
let quality: 'excellent' | 'good' | 'fair' | 'poor';
|
|
6047
|
+
if (qualityScore >= 0.8) quality = 'excellent';
|
|
6048
|
+
else if (qualityScore >= 0.6) quality = 'good';
|
|
6049
|
+
else if (qualityScore >= 0.4) quality = 'fair';
|
|
6050
|
+
else quality = 'poor';
|
|
5922
6051
|
|
|
5923
|
-
|
|
5924
|
-
|
|
5925
|
-
|
|
6052
|
+
return {
|
|
6053
|
+
quality,
|
|
6054
|
+
confidence: Math.round(qualityScore * 100),
|
|
6055
|
+
evidence: evidence.slice(0, 5), // Top 5 pieces of evidence
|
|
6056
|
+
gaps: gaps.slice(0, 3) // Top 3 gaps identified
|
|
6057
|
+
};
|
|
6058
|
+
}
|
|
6059
|
+
|
|
6060
|
+
private assessImplementationQuality(text: string, safeguard: SafeguardElement, evidence: string[], gaps: string[]): number {
|
|
6061
|
+
// Assess quality of direct implementation capability
|
|
6062
|
+
const implementationIndicators = this.getImplementationIndicators(safeguard.id);
|
|
6063
|
+
let score = 0;
|
|
5926
6064
|
|
|
5927
|
-
|
|
5928
|
-
|
|
5929
|
-
|
|
5930
|
-
|
|
6065
|
+
// Check for strong implementation language
|
|
6066
|
+
const strongIndicators = implementationIndicators.filter(indicator => text.includes(indicator.toLowerCase()));
|
|
6067
|
+
if (strongIndicators.length > 0) {
|
|
6068
|
+
score += 0.4;
|
|
6069
|
+
evidence.push(`Strong implementation indicators: ${strongIndicators.join(', ')}`);
|
|
6070
|
+
}
|
|
5931
6071
|
|
|
5932
|
-
|
|
5933
|
-
|
|
6072
|
+
// Check for comprehensive functionality description
|
|
6073
|
+
if (text.includes('comprehensive') || text.includes('complete') || text.includes('full')) {
|
|
6074
|
+
score += 0.2;
|
|
6075
|
+
evidence.push('Claims comprehensive functionality');
|
|
6076
|
+
}
|
|
5934
6077
|
|
|
5935
|
-
//
|
|
5936
|
-
if (
|
|
5937
|
-
|
|
6078
|
+
// Check for automated vs manual implementation
|
|
6079
|
+
if (text.includes('automat') || text.includes('real-time') || text.includes('continuous')) {
|
|
6080
|
+
score += 0.2;
|
|
6081
|
+
evidence.push('Automated implementation capability');
|
|
5938
6082
|
}
|
|
5939
|
-
|
|
5940
|
-
|
|
5941
|
-
|
|
6083
|
+
|
|
6084
|
+
// Identify potential gaps
|
|
6085
|
+
if (strongIndicators.length === 0) {
|
|
6086
|
+
gaps.push('No clear implementation indicators found');
|
|
5942
6087
|
}
|
|
6088
|
+
|
|
6089
|
+
return Math.min(score, 1.0);
|
|
6090
|
+
}
|
|
5943
6091
|
|
|
5944
|
-
|
|
5945
|
-
|
|
6092
|
+
private assessGovernanceQuality(text: string, safeguard: SafeguardElement, evidence: string[], gaps: string[]): number {
|
|
6093
|
+
const governanceIndicators = ['policy', 'process', 'governance', 'compliance', 'documentation', 'oversight'];
|
|
6094
|
+
let score = 0;
|
|
6095
|
+
|
|
6096
|
+
const foundIndicators = governanceIndicators.filter(indicator => text.includes(indicator));
|
|
6097
|
+
if (foundIndicators.length >= 3) {
|
|
6098
|
+
score += 0.5;
|
|
6099
|
+
evidence.push(`Strong governance capability: ${foundIndicators.join(', ')}`);
|
|
6100
|
+
}
|
|
5946
6101
|
|
|
5947
|
-
if (
|
|
5948
|
-
|
|
5949
|
-
|
|
5950
|
-
(facilitatesScore > 0.4 && facilitatesScore > governanceScore * 1.2)) {
|
|
5951
|
-
// Prioritize facilitation when:
|
|
5952
|
-
// 1. Clear facilitation language patterns detected, OR
|
|
5953
|
-
// 2. Explicit non-implementation language (tool doesn't directly implement), OR
|
|
5954
|
-
// 3. Facilitates score is substantial AND significantly higher than governance
|
|
5955
|
-
primaryCapability = 'facilitates';
|
|
5956
|
-
} else if (partialCapability) {
|
|
5957
|
-
primaryCapability = 'partial';
|
|
5958
|
-
} else if (governanceCapability && (facilitatesCapability || validatesCapability)) {
|
|
5959
|
-
// Tools that primarily manage governance but also facilitate/validate
|
|
5960
|
-
primaryCapability = 'governance';
|
|
5961
|
-
} else if (governanceScore > facilitatesScore && governanceCapability) {
|
|
5962
|
-
// Pure governance tools
|
|
5963
|
-
primaryCapability = 'governance';
|
|
5964
|
-
} else if (validatesScore > facilitatesScore && validatesCapability) {
|
|
5965
|
-
// Validation-focused tools
|
|
5966
|
-
primaryCapability = 'validates';
|
|
5967
|
-
} else if (facilitatesCapability) {
|
|
5968
|
-
// Default facilitation
|
|
5969
|
-
primaryCapability = 'facilitates';
|
|
6102
|
+
if (text.includes('documented') && text.includes('process')) {
|
|
6103
|
+
score += 0.3;
|
|
6104
|
+
evidence.push('Documented process management');
|
|
5970
6105
|
}
|
|
6106
|
+
|
|
6107
|
+
return Math.min(score, 1.0);
|
|
6108
|
+
}
|
|
5971
6109
|
|
|
5972
|
-
|
|
5973
|
-
const
|
|
6110
|
+
private assessFacilitationQuality(text: string, safeguard: SafeguardElement, evidence: string[], gaps: string[]): number {
|
|
6111
|
+
const facilitationIndicators = ['enhance', 'enable', 'support', 'facilitate', 'improve', 'optimize'];
|
|
6112
|
+
let score = 0;
|
|
6113
|
+
|
|
6114
|
+
const foundIndicators = facilitationIndicators.filter(indicator => text.includes(indicator));
|
|
6115
|
+
if (foundIndicators.length >= 2) {
|
|
6116
|
+
score += 0.4;
|
|
6117
|
+
evidence.push(`Clear facilitation capability: ${foundIndicators.join(', ')}`);
|
|
6118
|
+
}
|
|
6119
|
+
|
|
6120
|
+
return Math.min(score, 1.0);
|
|
6121
|
+
}
|
|
5974
6122
|
|
|
5975
|
-
|
|
5976
|
-
const
|
|
6123
|
+
private assessValidationQuality(text: string, safeguard: SafeguardElement, evidence: string[], gaps: string[]): number {
|
|
6124
|
+
const validationIndicators = ['audit', 'report', 'monitor', 'track', 'verify', 'validate'];
|
|
6125
|
+
let score = 0;
|
|
5977
6126
|
|
|
5978
|
-
const
|
|
5979
|
-
|
|
5980
|
-
|
|
5981
|
-
|
|
6127
|
+
const foundIndicators = validationIndicators.filter(indicator => text.includes(indicator));
|
|
6128
|
+
if (foundIndicators.length >= 2) {
|
|
6129
|
+
score += 0.4;
|
|
6130
|
+
evidence.push(`Strong validation capability: ${foundIndicators.join(', ')}`);
|
|
6131
|
+
}
|
|
5982
6132
|
|
|
5983
|
-
|
|
5984
|
-
|
|
5985
|
-
100
|
|
5986
|
-
);
|
|
6133
|
+
return Math.min(score, 1.0);
|
|
6134
|
+
}
|
|
5987
6135
|
|
|
6136
|
+
private generateCapabilityAnalysis(vendorName: string, safeguard: SafeguardElement, responseText: string,
|
|
6137
|
+
claimedCapability: string, qualityAssessment: any): VendorAnalysis {
|
|
6138
|
+
// Generate the new capability-focused analysis result
|
|
5988
6139
|
return {
|
|
5989
6140
|
vendor: vendorName,
|
|
5990
6141
|
safeguardId: safeguard.id,
|
|
5991
6142
|
safeguardTitle: safeguard.title,
|
|
5992
|
-
capability:
|
|
6143
|
+
capability: claimedCapability as 'full' | 'partial' | 'facilitates' | 'governance' | 'validates',
|
|
5993
6144
|
capabilities: {
|
|
5994
|
-
full:
|
|
5995
|
-
partial:
|
|
5996
|
-
facilitates:
|
|
5997
|
-
governance:
|
|
5998
|
-
validates:
|
|
5999
|
-
},
|
|
6000
|
-
confidence: Math.round(confidence),
|
|
6001
|
-
reasoning: this.generateCapabilityReasoning(primaryCapability, fullCapability, partialCapability, governanceCapability, facilitatesCapability, validatesCapability, coreCoverage, subElementCoverage, safeguard, hasFacilitationPattern, hasNonImplementationLanguage),
|
|
6002
|
-
evidence,
|
|
6003
|
-
elementsCovered: {
|
|
6004
|
-
coreRequirements: coreCoverage.coveredElements,
|
|
6005
|
-
subTaxonomicalElements: subElementCoverage.coveredElements,
|
|
6006
|
-
governanceElements: governanceCoverage.coveredElements,
|
|
6007
|
-
implementationMethods: implementationCoverage.coveredElements
|
|
6145
|
+
full: claimedCapability === 'full',
|
|
6146
|
+
partial: claimedCapability === 'partial',
|
|
6147
|
+
facilitates: claimedCapability === 'facilitates',
|
|
6148
|
+
governance: claimedCapability === 'governance',
|
|
6149
|
+
validates: claimedCapability === 'validates'
|
|
6008
6150
|
},
|
|
6009
|
-
|
|
6010
|
-
|
|
6011
|
-
|
|
6012
|
-
|
|
6151
|
+
confidence: qualityAssessment.confidence,
|
|
6152
|
+
reasoning: this.generateCapabilityReasoning(claimedCapability, qualityAssessment, safeguard),
|
|
6153
|
+
evidence: qualityAssessment.evidence,
|
|
6154
|
+
// Note: elementsCovered is now less relevant in capability-focused analysis
|
|
6155
|
+
// We focus on tool capability rather than element coverage
|
|
6156
|
+
toolCapabilityDescription: this.generateToolCapabilityDescription(claimedCapability, qualityAssessment),
|
|
6157
|
+
recommendedUse: this.generateRecommendedUse(claimedCapability, safeguard)
|
|
6158
|
+
};
|
|
6159
|
+
}
|
|
6160
|
+
|
|
6161
|
+
private generateCapabilityReasoning(claimedCapability: string, qualityAssessment: any, safeguard: SafeguardElement): string {
|
|
6162
|
+
const capabilityDescriptions = {
|
|
6163
|
+
full: "directly implements the core functionality of this safeguard",
|
|
6164
|
+
partial: "implements limited aspects of this safeguard with clear scope boundaries",
|
|
6165
|
+
facilitates: "enhances or enables the implementation of this safeguard by others",
|
|
6166
|
+
governance: "provides governance, policy, and oversight capabilities for this safeguard",
|
|
6167
|
+
validates: "provides evidence, audit, and compliance validation for this safeguard"
|
|
6168
|
+
};
|
|
6169
|
+
|
|
6170
|
+
const qualityDescriptor = qualityAssessment.quality;
|
|
6171
|
+
const description = capabilityDescriptions[claimedCapability as keyof typeof capabilityDescriptions];
|
|
6172
|
+
|
|
6173
|
+
return `This tool ${description} with ${qualityDescriptor} capability quality. ${qualityAssessment.evidence.length > 0 ? 'Evidence: ' + qualityAssessment.evidence.join('; ') : ''}`;
|
|
6174
|
+
}
|
|
6175
|
+
|
|
6176
|
+
private generateToolCapabilityDescription(claimedCapability: string, qualityAssessment: any): string {
|
|
6177
|
+
const roleDescriptions = {
|
|
6178
|
+
full: "Core Implementation Tool - Directly performs the safeguard functionality",
|
|
6179
|
+
partial: "Focused Implementation Tool - Performs specific aspects of the safeguard",
|
|
6180
|
+
facilitates: "Enablement Tool - Helps organizations implement the safeguard more effectively",
|
|
6181
|
+
governance: "Governance Tool - Manages policies, processes, and oversight for the safeguard",
|
|
6182
|
+
validates: "Compliance Tool - Provides audit, evidence, and validation capabilities"
|
|
6183
|
+
};
|
|
6184
|
+
|
|
6185
|
+
return roleDescriptions[claimedCapability as keyof typeof roleDescriptions] || "Support Tool";
|
|
6186
|
+
}
|
|
6187
|
+
|
|
6188
|
+
private generateRecommendedUse(claimedCapability: string, safeguard: SafeguardElement): string {
|
|
6189
|
+
const recommendations = {
|
|
6190
|
+
full: `Use as primary implementation tool for ${safeguard.title}. Ensure proper configuration and integration.`,
|
|
6191
|
+
partial: `Use as part of a multi-tool strategy for ${safeguard.title}. Supplement with additional capabilities as needed.`,
|
|
6192
|
+
facilitates: `Use to enhance existing safeguard implementation. Combine with direct implementation tools.`,
|
|
6193
|
+
governance: `Use for policy management and governance oversight. Pair with implementation and validation tools.`,
|
|
6194
|
+
validates: `Use for compliance monitoring and evidence collection. Combine with implementation tools for complete coverage.`
|
|
6013
6195
|
};
|
|
6196
|
+
|
|
6197
|
+
return recommendations[claimedCapability as keyof typeof recommendations] || "Evaluate specific use case alignment.";
|
|
6014
6198
|
}
|
|
6015
6199
|
|
|
6016
6200
|
private calculateKeywordScore(text: string, keywords: string[]): number {
|
|
6017
|
-
let
|
|
6018
|
-
let
|
|
6201
|
+
let matchedKeywords = 0;
|
|
6202
|
+
let totalMatches = 0;
|
|
6019
6203
|
|
|
6020
6204
|
keywords.forEach(keyword => {
|
|
6021
6205
|
const regex = new RegExp(keyword.replace(/\s+/g, '\\s+'), 'gi');
|
|
6022
6206
|
const keywordMatches = (text.match(regex) || []).length;
|
|
6023
6207
|
if (keywordMatches > 0) {
|
|
6024
|
-
|
|
6025
|
-
|
|
6208
|
+
matchedKeywords++;
|
|
6209
|
+
totalMatches += keywordMatches;
|
|
6026
6210
|
}
|
|
6027
6211
|
});
|
|
6028
6212
|
|
|
6029
|
-
|
|
6213
|
+
// Return percentage of keywords that were found, with bonus for multiple matches
|
|
6214
|
+
const baseScore = matchedKeywords / keywords.length;
|
|
6215
|
+
const matchBonus = Math.min(totalMatches * 0.1, 0.5); // Up to 50% bonus for multiple matches
|
|
6216
|
+
return Math.min(baseScore + matchBonus, 1.0);
|
|
6030
6217
|
}
|
|
6031
6218
|
|
|
6032
6219
|
private analyzeElementCoverage(text: string, elements: string[]): {
|
|
@@ -6168,76 +6355,6 @@ export class GRCAnalysisServer {
|
|
|
6168
6355
|
return reasons.join('. ');
|
|
6169
6356
|
}
|
|
6170
6357
|
|
|
6171
|
-
private generateCapabilityReasoning(
|
|
6172
|
-
primaryCapability: string,
|
|
6173
|
-
full: boolean,
|
|
6174
|
-
partial: boolean,
|
|
6175
|
-
governance: boolean,
|
|
6176
|
-
facilitates: boolean,
|
|
6177
|
-
validates: boolean,
|
|
6178
|
-
coreCoverage: any,
|
|
6179
|
-
subElementCoverage: any,
|
|
6180
|
-
safeguard: SafeguardElement,
|
|
6181
|
-
hasFacilitationPattern: boolean = false,
|
|
6182
|
-
hasNonImplementationLanguage: boolean = false
|
|
6183
|
-
): string {
|
|
6184
|
-
const reasons = [];
|
|
6185
|
-
|
|
6186
|
-
// Primary capability explanation
|
|
6187
|
-
switch (primaryCapability) {
|
|
6188
|
-
case 'full':
|
|
6189
|
-
reasons.push(`Provides FULL coverage of ${safeguard.title} - directly implements all core and sub-taxonomical elements`);
|
|
6190
|
-
break;
|
|
6191
|
-
case 'partial':
|
|
6192
|
-
reasons.push(`Provides PARTIAL coverage of ${safeguard.title} - directly implements some but not all core and sub-taxonomical elements`);
|
|
6193
|
-
break;
|
|
6194
|
-
case 'facilitates':
|
|
6195
|
-
if (hasFacilitationPattern || hasNonImplementationLanguage || governance) {
|
|
6196
|
-
reasons.push(`FACILITATES ${safeguard.title} by creating governance frameworks, policy infrastructure, and compliance processes that enable organizations to implement the control effectively`);
|
|
6197
|
-
} else {
|
|
6198
|
-
reasons.push(`FACILITATES ${safeguard.title} through data integration, automation, or technical capabilities that support implementation`);
|
|
6199
|
-
}
|
|
6200
|
-
break;
|
|
6201
|
-
case 'governance':
|
|
6202
|
-
reasons.push(`Provides GOVERNANCE capabilities for ${safeguard.title} through centralized policy management, process controls, and compliance oversight`);
|
|
6203
|
-
break;
|
|
6204
|
-
case 'validates':
|
|
6205
|
-
reasons.push(`VALIDATES ${safeguard.title} implementation through evidence collection, compliance reporting, and audit capabilities`);
|
|
6206
|
-
break;
|
|
6207
|
-
default:
|
|
6208
|
-
reasons.push(`No clear capability identified for ${safeguard.title}`);
|
|
6209
|
-
}
|
|
6210
|
-
|
|
6211
|
-
// Coverage details
|
|
6212
|
-
if (coreCoverage.coveredElements.length > 0) {
|
|
6213
|
-
reasons.push(`Core elements addressed: ${coreCoverage.coveredElements.length}/${safeguard.coreRequirements.length}`);
|
|
6214
|
-
}
|
|
6215
|
-
if (subElementCoverage.coveredElements.length > 0) {
|
|
6216
|
-
reasons.push(`Sub-taxonomical elements addressed: ${subElementCoverage.coveredElements.length}/${safeguard.subTaxonomicalElements.length}`);
|
|
6217
|
-
}
|
|
6218
|
-
|
|
6219
|
-
// Additional context for facilitation tools
|
|
6220
|
-
if (primaryCapability === 'facilitates') {
|
|
6221
|
-
if (hasFacilitationPattern || hasNonImplementationLanguage || governance) {
|
|
6222
|
-
reasons.push(`Note: This type of facilitation tool works alongside technical implementation solutions (asset scanners, MDM tools, etc.) to provide comprehensive control coverage`);
|
|
6223
|
-
}
|
|
6224
|
-
if (hasNonImplementationLanguage) {
|
|
6225
|
-
reasons.push(`Tool explicitly enables compliance through governance/process rather than direct technical implementation`);
|
|
6226
|
-
}
|
|
6227
|
-
}
|
|
6228
|
-
|
|
6229
|
-
// Multi-capability products
|
|
6230
|
-
const capabilityFlags = [governance, facilitates, validates].filter(Boolean);
|
|
6231
|
-
if (capabilityFlags.length > 1) {
|
|
6232
|
-
const capabilities = [];
|
|
6233
|
-
if (governance) capabilities.push('governance');
|
|
6234
|
-
if (facilitates) capabilities.push('facilitates');
|
|
6235
|
-
if (validates) capabilities.push('validates');
|
|
6236
|
-
reasons.push(`Multi-capability product with: ${capabilities.join(', ')}`);
|
|
6237
|
-
}
|
|
6238
|
-
|
|
6239
|
-
return reasons.join('. ');
|
|
6240
|
-
}
|
|
6241
6358
|
|
|
6242
6359
|
private validateClaim(claim: string, analysis: VendorAnalysis, capabilities: string[], safeguard: SafeguardElement) {
|
|
6243
6360
|
const validation = {
|
|
@@ -6253,16 +6370,14 @@ export class GRCAnalysisServer {
|
|
|
6253
6370
|
validation.coverageClaimValid = meetsFullCriteria;
|
|
6254
6371
|
|
|
6255
6372
|
if (!meetsFullCriteria) {
|
|
6256
|
-
|
|
6257
|
-
const coveredElements = analysis.elementsCovered.coreRequirements.length + analysis.elementsCovered.subTaxonomicalElements.length;
|
|
6258
|
-
validation.gaps.push(`FULL coverage claim not supported: Only ${coveredElements}/${totalElements} core and sub-taxonomical elements covered`);
|
|
6373
|
+
validation.gaps.push(`FULL implementation capability claim not supported: Tool does not demonstrate direct implementation of core safeguard functionality`);
|
|
6259
6374
|
}
|
|
6260
6375
|
} else if (claim === 'PARTIAL') {
|
|
6261
6376
|
const meetsPartialCriteria = analysis.capabilities.partial || analysis.capabilities.full;
|
|
6262
6377
|
validation.coverageClaimValid = meetsPartialCriteria;
|
|
6263
6378
|
|
|
6264
6379
|
if (!meetsPartialCriteria) {
|
|
6265
|
-
validation.gaps.push(`PARTIAL
|
|
6380
|
+
validation.gaps.push(`PARTIAL implementation capability claim questionable: No core or sub-taxonomical elements clearly addressed`);
|
|
6266
6381
|
}
|
|
6267
6382
|
}
|
|
6268
6383
|
|
|
@@ -6308,13 +6423,15 @@ export class GRCAnalysisServer {
|
|
|
6308
6423
|
} else {
|
|
6309
6424
|
validation.recommendations.push(`Consider requesting additional information about: ${validation.gaps.join(', ')}`);
|
|
6310
6425
|
|
|
6311
|
-
//
|
|
6312
|
-
if (analysis.
|
|
6313
|
-
validation.recommendations.push(
|
|
6314
|
-
}
|
|
6315
|
-
|
|
6316
|
-
if (analysis.
|
|
6317
|
-
validation.recommendations.push(
|
|
6426
|
+
// Capability-based recommendations
|
|
6427
|
+
if (analysis.capability === 'facilitates') {
|
|
6428
|
+
validation.recommendations.push('Consider pairing with direct implementation tools for complete safeguard coverage');
|
|
6429
|
+
} else if (analysis.capability === 'partial') {
|
|
6430
|
+
validation.recommendations.push('Evaluate scope limitations and identify complementary tools for full coverage');
|
|
6431
|
+
} else if (analysis.capability === 'governance') {
|
|
6432
|
+
validation.recommendations.push('Combine with technical implementation tools for complete safeguard execution');
|
|
6433
|
+
} else if (analysis.capability === 'validates') {
|
|
6434
|
+
validation.recommendations.push('Pair with implementation tools to ensure both execution and validation coverage');
|
|
6318
6435
|
}
|
|
6319
6436
|
|
|
6320
6437
|
if (!analysis.capabilities.validates && capabilities.includes('Validates')) {
|
|
@@ -6328,10 +6445,12 @@ export class GRCAnalysisServer {
|
|
|
6328
6445
|
private async validateVendorMapping(args: any) {
|
|
6329
6446
|
const { vendor_name = 'Unknown Vendor', safeguard_id, claimed_capability, supporting_text } = args;
|
|
6330
6447
|
|
|
6448
|
+
// Input validation
|
|
6449
|
+
this.validateSafeguardId(safeguard_id);
|
|
6450
|
+
this.validateTextInput(supporting_text, 'Supporting text');
|
|
6451
|
+
this.validateCapability(claimed_capability);
|
|
6452
|
+
|
|
6331
6453
|
const safeguard = CIS_SAFEGUARDS[safeguard_id];
|
|
6332
|
-
if (!safeguard) {
|
|
6333
|
-
throw new Error(`Safeguard ${safeguard_id} not found. Available safeguards: ${Object.keys(CIS_SAFEGUARDS).join(', ')}`);
|
|
6334
|
-
}
|
|
6335
6454
|
|
|
6336
6455
|
const validation = this.validateCapabilityClaim(
|
|
6337
6456
|
vendor_name,
|
|
@@ -6358,30 +6477,38 @@ export class GRCAnalysisServer {
|
|
|
6358
6477
|
): ValidationResult {
|
|
6359
6478
|
const text = supportingText.toLowerCase();
|
|
6360
6479
|
|
|
6361
|
-
//
|
|
6362
|
-
const
|
|
6480
|
+
// Detect tool type and validate domain match
|
|
6481
|
+
const detectedToolType = this.detectToolType(supportingText, safeguard.id);
|
|
6482
|
+
const domainValidation = this.validateDomainMatch(safeguard.id, claimedCapability, detectedToolType);
|
|
6363
6483
|
|
|
6364
|
-
//
|
|
6365
|
-
|
|
6366
|
-
|
|
6367
|
-
const governanceCoverage = this.analyzeBinaryElementCoverage(text, safeguard.governanceElements);
|
|
6484
|
+
// Adjust capability if domain mismatch detected
|
|
6485
|
+
let effectiveCapability = claimedCapability;
|
|
6486
|
+
let originalClaim: string | undefined;
|
|
6368
6487
|
|
|
6369
|
-
|
|
6370
|
-
|
|
6371
|
-
|
|
6372
|
-
|
|
6373
|
-
|
|
6374
|
-
|
|
6375
|
-
|
|
6376
|
-
|
|
6377
|
-
|
|
6378
|
-
|
|
6379
|
-
|
|
6380
|
-
|
|
6381
|
-
|
|
6382
|
-
|
|
6488
|
+
if (domainValidation.should_adjust_capability) {
|
|
6489
|
+
originalClaim = claimedCapability;
|
|
6490
|
+
effectiveCapability = domainValidation.adjusted_capability!;
|
|
6491
|
+
}
|
|
6492
|
+
|
|
6493
|
+
// Perform capability-focused analysis of the supporting text
|
|
6494
|
+
const actualAnalysis = this.performCapabilityAnalysis(vendorName, safeguard, supportingText);
|
|
6495
|
+
|
|
6496
|
+
// Validate claimed capability against actual capability analysis and domain requirements
|
|
6497
|
+
const validation = this.assessCapabilityClaimAlignment(
|
|
6498
|
+
claimedCapability,
|
|
6499
|
+
effectiveCapability,
|
|
6500
|
+
actualAnalysis,
|
|
6501
|
+
domainValidation,
|
|
6383
6502
|
text
|
|
6384
6503
|
);
|
|
6504
|
+
|
|
6505
|
+
// Add domain validation gaps if capability was adjusted
|
|
6506
|
+
if (domainValidation.should_adjust_capability) {
|
|
6507
|
+
validation.gaps.unshift(`Domain mismatch: ${domainValidation.reasoning}`);
|
|
6508
|
+
validation.recommendations.unshift(`Correct capability mapping should be '${effectiveCapability.toUpperCase()}' for ${detectedToolType} tools`);
|
|
6509
|
+
// Reduce confidence for domain mismatches
|
|
6510
|
+
validation.confidence = Math.max(validation.confidence - 20, 0);
|
|
6511
|
+
}
|
|
6385
6512
|
|
|
6386
6513
|
return {
|
|
6387
6514
|
vendor: vendorName,
|
|
@@ -6390,11 +6517,16 @@ export class GRCAnalysisServer {
|
|
|
6390
6517
|
claimed_capability: claimedCapability,
|
|
6391
6518
|
validation_status: validation.status,
|
|
6392
6519
|
confidence_score: validation.confidence,
|
|
6393
|
-
|
|
6394
|
-
|
|
6395
|
-
|
|
6396
|
-
|
|
6397
|
-
|
|
6520
|
+
actual_capability_detected: actualAnalysis.capability,
|
|
6521
|
+
capability_confidence: actualAnalysis.confidence,
|
|
6522
|
+
tool_capability_description: actualAnalysis.toolCapabilityDescription,
|
|
6523
|
+
recommended_use: actualAnalysis.recommendedUse,
|
|
6524
|
+
domain_validation: {
|
|
6525
|
+
required_tool_type: domainValidation.required_tool_types.join('/'),
|
|
6526
|
+
detected_tool_type: detectedToolType,
|
|
6527
|
+
domain_match: domainValidation.domain_match,
|
|
6528
|
+
capability_adjusted: domainValidation.should_adjust_capability,
|
|
6529
|
+
original_claim: originalClaim
|
|
6398
6530
|
},
|
|
6399
6531
|
gaps_identified: validation.gaps,
|
|
6400
6532
|
strengths_identified: validation.strengths,
|
|
@@ -6403,17 +6535,15 @@ export class GRCAnalysisServer {
|
|
|
6403
6535
|
};
|
|
6404
6536
|
}
|
|
6405
6537
|
|
|
6406
|
-
private
|
|
6538
|
+
private assessCapabilityClaimAlignment(
|
|
6407
6539
|
claimedCapability: string,
|
|
6540
|
+
effectiveCapability: string,
|
|
6408
6541
|
actualAnalysis: VendorAnalysis,
|
|
6409
|
-
|
|
6410
|
-
subElementPercentage: number,
|
|
6411
|
-
governancePercentage: number,
|
|
6542
|
+
domainValidation: any,
|
|
6412
6543
|
text: string
|
|
6413
6544
|
): {
|
|
6414
6545
|
status: 'SUPPORTED' | 'QUESTIONABLE' | 'UNSUPPORTED';
|
|
6415
6546
|
confidence: number;
|
|
6416
|
-
languageConsistency: number;
|
|
6417
6547
|
gaps: string[];
|
|
6418
6548
|
strengths: string[];
|
|
6419
6549
|
recommendations: string[];
|
|
@@ -6422,113 +6552,42 @@ export class GRCAnalysisServer {
|
|
|
6422
6552
|
const gaps: string[] = [];
|
|
6423
6553
|
const strengths: string[] = [];
|
|
6424
6554
|
const recommendations: string[] = [];
|
|
6425
|
-
|
|
6555
|
+
|
|
6556
|
+
// Compare claimed capability with what we actually detected
|
|
6557
|
+
const claimedLower = claimedCapability.toLowerCase();
|
|
6558
|
+
const effectiveLower = effectiveCapability.toLowerCase();
|
|
6559
|
+
const actualCapability = actualAnalysis.capability;
|
|
6560
|
+
|
|
6426
6561
|
let alignmentScore = 0;
|
|
6427
|
-
|
|
6428
|
-
|
|
6429
|
-
|
|
6430
|
-
|
|
6431
|
-
|
|
6432
|
-
|
|
6433
|
-
|
|
6434
|
-
|
|
6435
|
-
|
|
6436
|
-
|
|
6437
|
-
|
|
6438
|
-
|
|
6439
|
-
|
|
6440
|
-
|
|
6441
|
-
|
|
6442
|
-
|
|
6443
|
-
|
|
6444
|
-
// Check for conflicting facilitation language
|
|
6445
|
-
if (this.hasFacilitationLanguage(text)) {
|
|
6446
|
-
alignmentScore -= 30;
|
|
6447
|
-
gaps.push('Contains facilitation language inconsistent with FULL implementation claim');
|
|
6448
|
-
}
|
|
6449
|
-
|
|
6450
|
-
languageConsistency = this.assessImplementationLanguage(text);
|
|
6451
|
-
break;
|
|
6452
|
-
|
|
6453
|
-
case 'partial':
|
|
6454
|
-
// Validate PARTIAL claim
|
|
6455
|
-
if (corePercentage >= 30 || (corePercentage > 0 && subElementPercentage >= 20)) {
|
|
6456
|
-
alignmentScore = 75;
|
|
6457
|
-
strengths.push('Appropriate coverage level for PARTIAL implementation');
|
|
6458
|
-
} else {
|
|
6459
|
-
alignmentScore = Math.max(0, corePercentage + subElementPercentage - 10);
|
|
6460
|
-
gaps.push(`Coverage too low even for PARTIAL claim: ${Math.round(corePercentage)}% core, ${Math.round(subElementPercentage)}% sub-elements`);
|
|
6461
|
-
}
|
|
6462
|
-
|
|
6463
|
-
// Check for scope boundary definition
|
|
6464
|
-
if (this.hasScopeBoundaries(text)) {
|
|
6465
|
-
strengths.push('Clearly defines scope boundaries and limitations');
|
|
6466
|
-
alignmentScore += 10;
|
|
6467
|
-
} else {
|
|
6468
|
-
gaps.push('Should clearly define scope boundaries for PARTIAL implementation');
|
|
6469
|
-
recommendations.push('Specify exactly which elements are covered and which are not');
|
|
6470
|
-
}
|
|
6471
|
-
|
|
6472
|
-
languageConsistency = this.assessImplementationLanguage(text);
|
|
6473
|
-
break;
|
|
6474
|
-
|
|
6475
|
-
case 'facilitates':
|
|
6476
|
-
// Validate FACILITATES claim
|
|
6477
|
-
if (this.hasFacilitationLanguage(text) || actualAnalysis.capabilities.facilitates) {
|
|
6478
|
-
alignmentScore = 80;
|
|
6479
|
-
strengths.push('Contains appropriate facilitation and enablement language');
|
|
6480
|
-
} else {
|
|
6481
|
-
alignmentScore = 40;
|
|
6482
|
-
gaps.push('Lacks clear facilitation language (enables, supports, provides framework)');
|
|
6483
|
-
}
|
|
6484
|
-
|
|
6485
|
-
// Check that it doesn't claim direct implementation
|
|
6486
|
-
if (this.hasDirectImplementationLanguage(text)) {
|
|
6487
|
-
// Special handling: If it lacks facilitation language AND claims implementation, stay QUESTIONABLE
|
|
6488
|
-
if (alignmentScore <= 40) {
|
|
6489
|
-
alignmentScore = 45; // Keep it in QUESTIONABLE range
|
|
6490
|
-
} else {
|
|
6491
|
-
alignmentScore -= 15;
|
|
6492
|
-
}
|
|
6493
|
-
gaps.push('Claims direct implementation, inconsistent with FACILITATES capability');
|
|
6494
|
-
}
|
|
6495
|
-
|
|
6496
|
-
languageConsistency = this.assessFacilitationLanguage(text);
|
|
6497
|
-
break;
|
|
6498
|
-
|
|
6499
|
-
case 'governance':
|
|
6500
|
-
// Validate GOVERNANCE claim
|
|
6501
|
-
if (governancePercentage >= 60 || actualAnalysis.capabilities.governance) {
|
|
6502
|
-
alignmentScore = 85;
|
|
6503
|
-
strengths.push('Strong governance element coverage and policy management language');
|
|
6504
|
-
} else {
|
|
6505
|
-
alignmentScore = Math.max(30, governancePercentage);
|
|
6506
|
-
gaps.push(`Governance element coverage (${Math.round(governancePercentage)}%) below expected threshold (60%)`);
|
|
6507
|
-
}
|
|
6508
|
-
|
|
6509
|
-
languageConsistency = this.assessGovernanceLanguage(text);
|
|
6510
|
-
break;
|
|
6511
|
-
|
|
6512
|
-
case 'validates':
|
|
6513
|
-
// Validate VALIDATES claim
|
|
6514
|
-
if (actualAnalysis.capabilities.validates) {
|
|
6515
|
-
alignmentScore = 85;
|
|
6516
|
-
strengths.push('Contains evidence collection and reporting capabilities');
|
|
6517
|
-
} else {
|
|
6518
|
-
alignmentScore = 30;
|
|
6519
|
-
gaps.push('Lacks validation language (audit, report, evidence, verify, monitor)');
|
|
6520
|
-
}
|
|
6521
|
-
|
|
6522
|
-
languageConsistency = this.assessValidationLanguage(text);
|
|
6523
|
-
break;
|
|
6524
|
-
|
|
6525
|
-
default:
|
|
6526
|
-
alignmentScore = 0;
|
|
6527
|
-
gaps.push(`Unknown capability type: ${claimedCapability}`);
|
|
6528
|
-
languageConsistency = 0;
|
|
6562
|
+
|
|
6563
|
+
// Check if claim aligns with actual analysis
|
|
6564
|
+
if (claimedLower === actualCapability) {
|
|
6565
|
+
alignmentScore = actualAnalysis.confidence;
|
|
6566
|
+
strengths.push(`Claimed capability '${claimedCapability}' aligns with detected capability`);
|
|
6567
|
+
strengths.push(`Tool demonstrates appropriate ${actualAnalysis.toolCapabilityDescription.toLowerCase()}`);
|
|
6568
|
+
} else if (effectiveLower === actualCapability) {
|
|
6569
|
+
// Domain validation adjusted the capability and it matches the analysis
|
|
6570
|
+
alignmentScore = Math.max(actualAnalysis.confidence - 20, 30);
|
|
6571
|
+
gaps.push(`Original claim '${claimedCapability}' doesn't match tool type, adjusted to '${effectiveCapability}'`);
|
|
6572
|
+
strengths.push(`Adjusted capability '${effectiveCapability}' aligns with tool analysis`);
|
|
6573
|
+
} else {
|
|
6574
|
+
// Neither claimed nor effective capability matches the analysis
|
|
6575
|
+
alignmentScore = Math.max(actualAnalysis.confidence - 40, 10);
|
|
6576
|
+
gaps.push(`Claimed capability '${claimedCapability}' doesn't align with detected capability '${actualCapability}'`);
|
|
6577
|
+
gaps.push(`Tool appears to be: ${actualAnalysis.toolCapabilityDescription}`);
|
|
6529
6578
|
}
|
|
6530
|
-
|
|
6531
|
-
//
|
|
6579
|
+
|
|
6580
|
+
// Add evidence from the capability analysis
|
|
6581
|
+
if (actualAnalysis.evidence && actualAnalysis.evidence.length > 0) {
|
|
6582
|
+
strengths.push(`Supporting evidence: ${actualAnalysis.evidence.slice(0, 2).join('; ')}`);
|
|
6583
|
+
}
|
|
6584
|
+
|
|
6585
|
+
// Domain validation feedback
|
|
6586
|
+
if (!domainValidation.domain_match) {
|
|
6587
|
+
gaps.push(`Tool type '${domainValidation.detected_tool_type}' not appropriate for this safeguard domain`);
|
|
6588
|
+
}
|
|
6589
|
+
|
|
6590
|
+
// Determine overall status based on alignment score
|
|
6532
6591
|
let status: 'SUPPORTED' | 'QUESTIONABLE' | 'UNSUPPORTED';
|
|
6533
6592
|
if (alignmentScore >= 70) {
|
|
6534
6593
|
status = 'SUPPORTED';
|
|
@@ -6537,21 +6596,23 @@ export class GRCAnalysisServer {
|
|
|
6537
6596
|
} else {
|
|
6538
6597
|
status = 'UNSUPPORTED';
|
|
6539
6598
|
}
|
|
6540
|
-
|
|
6541
|
-
// Generate recommendations
|
|
6542
|
-
|
|
6543
|
-
|
|
6544
|
-
}
|
|
6599
|
+
|
|
6600
|
+
// Generate capability-focused recommendations
|
|
6601
|
+
recommendations.push(actualAnalysis.recommendedUse);
|
|
6602
|
+
|
|
6545
6603
|
if (status === 'QUESTIONABLE') {
|
|
6546
|
-
recommendations.push('
|
|
6604
|
+
recommendations.push('Consider clarifying tool capabilities or adjusting capability claim');
|
|
6547
6605
|
}
|
|
6548
|
-
|
|
6549
|
-
|
|
6606
|
+
|
|
6607
|
+
if (!domainValidation.domain_match) {
|
|
6608
|
+
recommendations.push(`For ${actualCapability.toUpperCase()} capability, focus on how the tool ${actualCapability === 'facilitates' ? 'enables and enhances' : actualCapability === 'governance' ? 'manages policies and processes for' : actualCapability === 'validates' ? 'provides evidence and reporting on' : 'directly implements'} this safeguard`);
|
|
6609
|
+
}
|
|
6610
|
+
|
|
6611
|
+
const feedback = this.generateCapabilityValidationFeedback(claimedCapability, effectiveCapability, actualCapability, status, alignmentScore, domainValidation);
|
|
6550
6612
|
|
|
6551
6613
|
return {
|
|
6552
6614
|
status,
|
|
6553
6615
|
confidence: Math.round(alignmentScore),
|
|
6554
|
-
languageConsistency: Math.round(languageConsistency),
|
|
6555
6616
|
gaps,
|
|
6556
6617
|
strengths,
|
|
6557
6618
|
recommendations,
|
|
@@ -6617,6 +6678,232 @@ export class GRCAnalysisServer {
|
|
|
6617
6678
|
return this.calculateKeywordScore(text, validationKeywords) * 100;
|
|
6618
6679
|
}
|
|
6619
6680
|
|
|
6681
|
+
private detectToolType(text: string, safeguardId?: string): string {
|
|
6682
|
+
const lowerText = text.toLowerCase();
|
|
6683
|
+
|
|
6684
|
+
// Enhanced keyword definitions with scoring weights and context
|
|
6685
|
+
const toolTypePatterns = {
|
|
6686
|
+
'inventory': {
|
|
6687
|
+
primary: [
|
|
6688
|
+
'asset management', 'inventory management', 'cmdb', 'configuration management database',
|
|
6689
|
+
'asset discovery', 'hardware inventory', 'software inventory', 'device inventory',
|
|
6690
|
+
'asset tracking', 'it asset management', 'endpoint discovery', 'asset lifecycle'
|
|
6691
|
+
],
|
|
6692
|
+
secondary: [
|
|
6693
|
+
'inventory', 'discovery', 'device management', 'endpoint management',
|
|
6694
|
+
'configuration management', 'asset database', 'equipment tracking'
|
|
6695
|
+
],
|
|
6696
|
+
weight: { primary: 3, secondary: 1 }
|
|
6697
|
+
},
|
|
6698
|
+
'identity_management': {
|
|
6699
|
+
primary: [
|
|
6700
|
+
'identity management', 'iam', 'active directory', 'identity provider',
|
|
6701
|
+
'single sign-on', 'sso', 'multi-factor authentication', 'mfa',
|
|
6702
|
+
'user management', 'account management', 'directory service'
|
|
6703
|
+
],
|
|
6704
|
+
secondary: [
|
|
6705
|
+
'ldap', 'authentication', 'access management', 'identity access management',
|
|
6706
|
+
'user directory', 'account lifecycle', 'privileged access'
|
|
6707
|
+
],
|
|
6708
|
+
weight: { primary: 3, secondary: 1 }
|
|
6709
|
+
},
|
|
6710
|
+
'vulnerability_management': {
|
|
6711
|
+
primary: [
|
|
6712
|
+
'vulnerability management', 'vulnerability scanner', 'patch management',
|
|
6713
|
+
'security scanning', 'vulnerability assessment', 'penetration testing'
|
|
6714
|
+
],
|
|
6715
|
+
secondary: [
|
|
6716
|
+
'vuln scan', 'security scanner', 'network scanner', 'scanning capabilities',
|
|
6717
|
+
'security assessment', 'vulnerability scanning', 'patch deployment'
|
|
6718
|
+
],
|
|
6719
|
+
weight: { primary: 3, secondary: 1 }
|
|
6720
|
+
},
|
|
6721
|
+
'threat_intelligence': {
|
|
6722
|
+
primary: [
|
|
6723
|
+
'threat intelligence', 'cyber threat intelligence', 'threat intel',
|
|
6724
|
+
'threat feed', 'ioc feed', 'security intelligence', 'threat data'
|
|
6725
|
+
],
|
|
6726
|
+
secondary: [
|
|
6727
|
+
'enrichment', 'data feed', 'contextual data', 'risk intelligence',
|
|
6728
|
+
'threat indicators', 'intelligence platform', 'threat correlation'
|
|
6729
|
+
],
|
|
6730
|
+
weight: { primary: 3, secondary: 1 }
|
|
6731
|
+
},
|
|
6732
|
+
'network_security': {
|
|
6733
|
+
primary: [
|
|
6734
|
+
'firewall', 'network access control', 'nac', 'intrusion detection',
|
|
6735
|
+
'network security', 'network segmentation'
|
|
6736
|
+
],
|
|
6737
|
+
secondary: [
|
|
6738
|
+
'network monitoring', 'traffic analysis', 'perimeter security',
|
|
6739
|
+
'network protection', 'network filtering'
|
|
6740
|
+
],
|
|
6741
|
+
weight: { primary: 3, secondary: 1 }
|
|
6742
|
+
},
|
|
6743
|
+
'governance': {
|
|
6744
|
+
primary: [
|
|
6745
|
+
'grc', 'governance risk compliance', 'compliance management',
|
|
6746
|
+
'policy management', 'risk management', 'audit management'
|
|
6747
|
+
],
|
|
6748
|
+
secondary: [
|
|
6749
|
+
'governance', 'compliance platform', 'policy enforcement',
|
|
6750
|
+
'regulatory compliance', 'framework management'
|
|
6751
|
+
],
|
|
6752
|
+
weight: { primary: 3, secondary: 1 }
|
|
6753
|
+
},
|
|
6754
|
+
'security_analytics': {
|
|
6755
|
+
primary: [
|
|
6756
|
+
'siem', 'security information event management', 'security analytics',
|
|
6757
|
+
'soar', 'security orchestration', 'log management'
|
|
6758
|
+
],
|
|
6759
|
+
secondary: [
|
|
6760
|
+
'security monitoring', 'event correlation', 'log analysis',
|
|
6761
|
+
'security intelligence', 'incident response platform'
|
|
6762
|
+
],
|
|
6763
|
+
weight: { primary: 3, secondary: 1 }
|
|
6764
|
+
}
|
|
6765
|
+
};
|
|
6766
|
+
|
|
6767
|
+
// Calculate scores for each tool type
|
|
6768
|
+
const toolScores: Record<string, number> = {};
|
|
6769
|
+
|
|
6770
|
+
for (const [toolType, patterns] of Object.entries(toolTypePatterns)) {
|
|
6771
|
+
let score = 0;
|
|
6772
|
+
|
|
6773
|
+
// Check primary keywords
|
|
6774
|
+
for (const keyword of patterns.primary) {
|
|
6775
|
+
if (lowerText.includes(keyword)) {
|
|
6776
|
+
score += patterns.weight.primary;
|
|
6777
|
+
}
|
|
6778
|
+
}
|
|
6779
|
+
|
|
6780
|
+
// Check secondary keywords
|
|
6781
|
+
for (const keyword of patterns.secondary) {
|
|
6782
|
+
if (lowerText.includes(keyword)) {
|
|
6783
|
+
score += patterns.weight.secondary;
|
|
6784
|
+
}
|
|
6785
|
+
}
|
|
6786
|
+
|
|
6787
|
+
toolScores[toolType] = score;
|
|
6788
|
+
}
|
|
6789
|
+
|
|
6790
|
+
// Apply safeguard-specific context weighting if provided
|
|
6791
|
+
if (safeguardId && toolScores) {
|
|
6792
|
+
const contextBonus = 1; // Small bonus for domain alignment
|
|
6793
|
+
|
|
6794
|
+
// Asset inventory safeguards (1.1, 1.2) favor inventory tools
|
|
6795
|
+
if (['1.1', '1.2'].includes(safeguardId) && toolScores['inventory'] > 0) {
|
|
6796
|
+
toolScores['inventory'] += contextBonus;
|
|
6797
|
+
}
|
|
6798
|
+
|
|
6799
|
+
// Account inventory safeguards (5.1, 5.2, 5.3) favor identity tools
|
|
6800
|
+
if (['5.1', '5.2', '5.3'].includes(safeguardId) && toolScores['identity_management'] > 0) {
|
|
6801
|
+
toolScores['identity_management'] += contextBonus;
|
|
6802
|
+
}
|
|
6803
|
+
|
|
6804
|
+
// Authentication safeguards (6.1, 6.2, 6.3) favor identity tools
|
|
6805
|
+
if (['6.1', '6.2', '6.3'].includes(safeguardId) && toolScores['identity_management'] > 0) {
|
|
6806
|
+
toolScores['identity_management'] += contextBonus;
|
|
6807
|
+
}
|
|
6808
|
+
|
|
6809
|
+
// Vulnerability safeguards (7.1-7.7) favor vulnerability management tools
|
|
6810
|
+
if (['7.1', '7.2', '7.3', '7.4', '7.5', '7.6', '7.7'].includes(safeguardId) && toolScores['vulnerability_management'] > 0) {
|
|
6811
|
+
toolScores['vulnerability_management'] += contextBonus;
|
|
6812
|
+
}
|
|
6813
|
+
}
|
|
6814
|
+
|
|
6815
|
+
// Find the tool type with highest score
|
|
6816
|
+
let maxScore = 0;
|
|
6817
|
+
let detectedType = 'unknown';
|
|
6818
|
+
|
|
6819
|
+
for (const [toolType, score] of Object.entries(toolScores)) {
|
|
6820
|
+
if (score > maxScore) {
|
|
6821
|
+
maxScore = score;
|
|
6822
|
+
detectedType = toolType;
|
|
6823
|
+
}
|
|
6824
|
+
}
|
|
6825
|
+
|
|
6826
|
+
// Require minimum score threshold to avoid false positives
|
|
6827
|
+
return maxScore >= 2 ? detectedType : 'unknown';
|
|
6828
|
+
}
|
|
6829
|
+
|
|
6830
|
+
private validateDomainMatch(
|
|
6831
|
+
safeguardId: string,
|
|
6832
|
+
claimedCapability: string,
|
|
6833
|
+
detectedToolType: string
|
|
6834
|
+
): {
|
|
6835
|
+
domain_match: boolean;
|
|
6836
|
+
required_tool_types: string[];
|
|
6837
|
+
should_adjust_capability: boolean;
|
|
6838
|
+
adjusted_capability?: string;
|
|
6839
|
+
reasoning: string;
|
|
6840
|
+
} {
|
|
6841
|
+
const domainReq = SAFEGUARD_DOMAIN_REQUIREMENTS[safeguardId];
|
|
6842
|
+
|
|
6843
|
+
if (!domainReq) {
|
|
6844
|
+
return {
|
|
6845
|
+
domain_match: true,
|
|
6846
|
+
required_tool_types: [],
|
|
6847
|
+
should_adjust_capability: false,
|
|
6848
|
+
reasoning: 'No domain restrictions defined for this safeguard'
|
|
6849
|
+
};
|
|
6850
|
+
}
|
|
6851
|
+
|
|
6852
|
+
const isFullOrPartial = ['full', 'partial'].includes(claimedCapability.toLowerCase());
|
|
6853
|
+
const toolTypeMatches = domainReq.required_tool_types.includes(detectedToolType);
|
|
6854
|
+
|
|
6855
|
+
if (isFullOrPartial && !toolTypeMatches) {
|
|
6856
|
+
return {
|
|
6857
|
+
domain_match: false,
|
|
6858
|
+
required_tool_types: domainReq.required_tool_types,
|
|
6859
|
+
should_adjust_capability: true,
|
|
6860
|
+
adjusted_capability: 'facilitates',
|
|
6861
|
+
reasoning: `${domainReq.domain} safeguard requires ${domainReq.required_tool_types.join('/')} tool types for FULL/PARTIAL implementation capability. Detected tool type '${detectedToolType}' can only facilitate implementation.`
|
|
6862
|
+
};
|
|
6863
|
+
}
|
|
6864
|
+
|
|
6865
|
+
return {
|
|
6866
|
+
domain_match: true,
|
|
6867
|
+
required_tool_types: domainReq.required_tool_types,
|
|
6868
|
+
should_adjust_capability: false,
|
|
6869
|
+
reasoning: toolTypeMatches ?
|
|
6870
|
+
`Tool type '${detectedToolType}' is appropriate for ${domainReq.domain} safeguard` :
|
|
6871
|
+
'No domain validation required for this capability type'
|
|
6872
|
+
};
|
|
6873
|
+
}
|
|
6874
|
+
|
|
6875
|
+
private generateCapabilityValidationFeedback(
|
|
6876
|
+
claimedCapability: string,
|
|
6877
|
+
effectiveCapability: string,
|
|
6878
|
+
actualCapability: string,
|
|
6879
|
+
status: string,
|
|
6880
|
+
score: number,
|
|
6881
|
+
domainValidation: any
|
|
6882
|
+
): string {
|
|
6883
|
+
let feedback = `Capability Validation: ${claimedCapability.toUpperCase()} claim is ${status} (${Math.round(score)}% confidence)\n\n`;
|
|
6884
|
+
|
|
6885
|
+
// Analysis summary
|
|
6886
|
+
feedback += `ANALYSIS:\n`;
|
|
6887
|
+
feedback += `• Claimed: ${claimedCapability.toUpperCase()}\n`;
|
|
6888
|
+
if (effectiveCapability !== claimedCapability) {
|
|
6889
|
+
feedback += `• Domain Adjusted: ${effectiveCapability.toUpperCase()} (${domainValidation.reasoning})\n`;
|
|
6890
|
+
}
|
|
6891
|
+
feedback += `• Detected: ${actualCapability.toUpperCase()}\n`;
|
|
6892
|
+
feedback += `• Tool Type: ${domainValidation.detected_tool_type}\n\n`;
|
|
6893
|
+
|
|
6894
|
+
// Assessment
|
|
6895
|
+
feedback += `ASSESSMENT: `;
|
|
6896
|
+
if (claimedCapability.toLowerCase() === actualCapability) {
|
|
6897
|
+
feedback += 'Claimed capability aligns perfectly with tool analysis.';
|
|
6898
|
+
} else if (effectiveCapability.toLowerCase() === actualCapability) {
|
|
6899
|
+
feedback += 'After domain validation adjustment, capability aligns with tool analysis.';
|
|
6900
|
+
} else {
|
|
6901
|
+
feedback += `Capability mismatch detected. Tool functions as ${actualCapability.toUpperCase()} rather than claimed ${claimedCapability.toUpperCase()}.`;
|
|
6902
|
+
}
|
|
6903
|
+
|
|
6904
|
+
return feedback;
|
|
6905
|
+
}
|
|
6906
|
+
|
|
6620
6907
|
private generateValidationFeedback(
|
|
6621
6908
|
claimedCapability: string,
|
|
6622
6909
|
status: string,
|
|
@@ -6624,7 +6911,7 @@ export class GRCAnalysisServer {
|
|
|
6624
6911
|
strengths: string[],
|
|
6625
6912
|
score: number
|
|
6626
6913
|
): string {
|
|
6627
|
-
let feedback = `Validation of ${claimedCapability.toUpperCase()} capability claim: ${status} (${Math.round(score)}% alignment)\n\n`;
|
|
6914
|
+
let feedback = `Validation of ${claimedCapability.toUpperCase()} capability role claim: ${status} (${Math.round(score)}% alignment)\n\n`;
|
|
6628
6915
|
|
|
6629
6916
|
if (strengths.length > 0) {
|
|
6630
6917
|
feedback += `STRENGTHS:\n${strengths.map(s => `• ${s}`).join('\n')}\n\n`;
|
|
@@ -6637,23 +6924,162 @@ export class GRCAnalysisServer {
|
|
|
6637
6924
|
feedback += `ASSESSMENT: `;
|
|
6638
6925
|
switch (status) {
|
|
6639
6926
|
case 'SUPPORTED':
|
|
6640
|
-
feedback += 'The vendor\'s supporting evidence strongly aligns with their claimed capability.';
|
|
6927
|
+
feedback += 'The vendor\'s supporting evidence strongly aligns with their claimed capability role.';
|
|
6641
6928
|
break;
|
|
6642
6929
|
case 'QUESTIONABLE':
|
|
6643
6930
|
feedback += 'The vendor\'s evidence partially supports their claim but has notable gaps or inconsistencies.';
|
|
6644
6931
|
break;
|
|
6645
6932
|
case 'UNSUPPORTED':
|
|
6646
|
-
feedback += 'The vendor\'s evidence does not adequately support their claimed capability.';
|
|
6933
|
+
feedback += 'The vendor\'s evidence does not adequately support their claimed capability role.';
|
|
6647
6934
|
break;
|
|
6648
6935
|
}
|
|
6649
6936
|
|
|
6650
6937
|
return feedback;
|
|
6651
6938
|
}
|
|
6652
6939
|
|
|
6940
|
+
// Enhanced error handling and formatting
|
|
6941
|
+
private formatErrorMessage(error: unknown, toolName: string): string {
|
|
6942
|
+
if (error instanceof Error) {
|
|
6943
|
+
// Production-friendly error messages
|
|
6944
|
+
switch (error.message) {
|
|
6945
|
+
case /^Safeguard .+ not found/.test(error.message) ? error.message : '':
|
|
6946
|
+
return `❌ Invalid safeguard ID. Use 'list_available_safeguards' to see available CIS Control safeguards.`;
|
|
6947
|
+
case /^Unknown tool/.test(error.message) ? error.message : '':
|
|
6948
|
+
return `❌ Tool '${toolName}' is not available. Available tools: analyze_vendor_response, validate_vendor_mapping, validate_coverage_claim, get_safeguard_details, list_available_safeguards.`;
|
|
6949
|
+
default:
|
|
6950
|
+
return `❌ Error in ${toolName}: ${error.message}`;
|
|
6951
|
+
}
|
|
6952
|
+
}
|
|
6953
|
+
return `❌ Unexpected error in ${toolName}: ${String(error)}`;
|
|
6954
|
+
}
|
|
6955
|
+
|
|
6956
|
+
// Performance monitoring and caching
|
|
6957
|
+
private performanceMetrics = {
|
|
6958
|
+
toolExecutionTimes: new Map<string, number[]>(),
|
|
6959
|
+
startTime: Date.now(),
|
|
6960
|
+
totalRequests: 0,
|
|
6961
|
+
errorCount: 0
|
|
6962
|
+
};
|
|
6963
|
+
|
|
6964
|
+
// Simple cache for safeguard details (most commonly requested data)
|
|
6965
|
+
private cache = {
|
|
6966
|
+
safeguardDetails: new Map<string, any>(),
|
|
6967
|
+
safeguardList: null as any,
|
|
6968
|
+
lastCacheCleanup: Date.now()
|
|
6969
|
+
};
|
|
6970
|
+
|
|
6971
|
+
private getCachedSafeguardDetails(safeguardId: string, includeExamples: boolean): any | null {
|
|
6972
|
+
const cacheKey = `${safeguardId}_${includeExamples}`;
|
|
6973
|
+
const cached = this.cache.safeguardDetails.get(cacheKey);
|
|
6974
|
+
|
|
6975
|
+
if (cached && (Date.now() - cached.timestamp < 5 * 60 * 1000)) { // 5 minute cache
|
|
6976
|
+
return cached.data;
|
|
6977
|
+
}
|
|
6978
|
+
|
|
6979
|
+
return null;
|
|
6980
|
+
}
|
|
6981
|
+
|
|
6982
|
+
private setCachedSafeguardDetails(safeguardId: string, includeExamples: boolean, data: any): void {
|
|
6983
|
+
const cacheKey = `${safeguardId}_${includeExamples}`;
|
|
6984
|
+
this.cache.safeguardDetails.set(cacheKey, {
|
|
6985
|
+
data,
|
|
6986
|
+
timestamp: Date.now()
|
|
6987
|
+
});
|
|
6988
|
+
|
|
6989
|
+
// Periodic cache cleanup to prevent memory leaks
|
|
6990
|
+
if (Date.now() - this.cache.lastCacheCleanup > 10 * 60 * 1000) { // 10 minutes
|
|
6991
|
+
this.cleanupCache();
|
|
6992
|
+
}
|
|
6993
|
+
}
|
|
6994
|
+
|
|
6995
|
+
private cleanupCache(): void {
|
|
6996
|
+
const now = Date.now();
|
|
6997
|
+
const maxAge = 10 * 60 * 1000; // 10 minutes
|
|
6998
|
+
|
|
6999
|
+
// Clean up safeguard details cache
|
|
7000
|
+
for (const [key, value] of this.cache.safeguardDetails.entries()) {
|
|
7001
|
+
if (now - value.timestamp > maxAge) {
|
|
7002
|
+
this.cache.safeguardDetails.delete(key);
|
|
7003
|
+
}
|
|
7004
|
+
}
|
|
7005
|
+
|
|
7006
|
+
this.cache.lastCacheCleanup = now;
|
|
7007
|
+
}
|
|
7008
|
+
|
|
7009
|
+
private recordToolExecution(toolName: string, executionTime: number) {
|
|
7010
|
+
this.performanceMetrics.totalRequests++;
|
|
7011
|
+
|
|
7012
|
+
if (!this.performanceMetrics.toolExecutionTimes.has(toolName)) {
|
|
7013
|
+
this.performanceMetrics.toolExecutionTimes.set(toolName, []);
|
|
7014
|
+
}
|
|
7015
|
+
|
|
7016
|
+
const times = this.performanceMetrics.toolExecutionTimes.get(toolName)!;
|
|
7017
|
+
times.push(executionTime);
|
|
7018
|
+
|
|
7019
|
+
// Keep only last 100 measurements for memory efficiency
|
|
7020
|
+
if (times.length > 100) {
|
|
7021
|
+
times.shift();
|
|
7022
|
+
}
|
|
7023
|
+
}
|
|
7024
|
+
|
|
7025
|
+
private getPerformanceStats(): string {
|
|
7026
|
+
const uptime = Date.now() - this.performanceMetrics.startTime;
|
|
7027
|
+
const avgTimes = Array.from(this.performanceMetrics.toolExecutionTimes.entries())
|
|
7028
|
+
.map(([tool, times]) => {
|
|
7029
|
+
const avg = times.reduce((a, b) => a + b, 0) / times.length;
|
|
7030
|
+
return `${tool}: ${avg.toFixed(2)}ms`;
|
|
7031
|
+
});
|
|
7032
|
+
|
|
7033
|
+
return `Performance Stats (Uptime: ${(uptime / 1000).toFixed(1)}s, Requests: ${this.performanceMetrics.totalRequests}, Errors: ${this.performanceMetrics.errorCount})\n${avgTimes.join(', ')}`;
|
|
7034
|
+
}
|
|
7035
|
+
|
|
7036
|
+
// Input validation and sanitization
|
|
7037
|
+
private validateSafeguardId(safeguardId: string): void {
|
|
7038
|
+
if (!safeguardId || typeof safeguardId !== 'string') {
|
|
7039
|
+
throw new Error('Safeguard ID is required and must be a string');
|
|
7040
|
+
}
|
|
7041
|
+
|
|
7042
|
+
if (!/^[0-9]+\.[0-9]+$/.test(safeguardId)) {
|
|
7043
|
+
throw new Error('Safeguard ID must be in format "X.Y" (e.g., "1.1", "5.1")');
|
|
7044
|
+
}
|
|
7045
|
+
|
|
7046
|
+
if (!CIS_SAFEGUARDS[safeguardId]) {
|
|
7047
|
+
throw new Error(`Safeguard ${safeguardId} not found`);
|
|
7048
|
+
}
|
|
7049
|
+
}
|
|
7050
|
+
|
|
7051
|
+
private validateTextInput(text: string, fieldName: string): void {
|
|
7052
|
+
if (!text || typeof text !== 'string') {
|
|
7053
|
+
throw new Error(`${fieldName} is required and must be a string`);
|
|
7054
|
+
}
|
|
7055
|
+
|
|
7056
|
+
if (text.length > 10000) {
|
|
7057
|
+
throw new Error(`${fieldName} must be less than 10,000 characters`);
|
|
7058
|
+
}
|
|
7059
|
+
|
|
7060
|
+
if (text.trim().length < 10) {
|
|
7061
|
+
throw new Error(`${fieldName} must contain at least 10 meaningful characters`);
|
|
7062
|
+
}
|
|
7063
|
+
}
|
|
7064
|
+
|
|
7065
|
+
private validateCapability(capability: string): void {
|
|
7066
|
+
const validCapabilities = ['full', 'partial', 'facilitates', 'governance', 'validates'];
|
|
7067
|
+
if (!validCapabilities.includes(capability.toLowerCase())) {
|
|
7068
|
+
throw new Error(`Invalid capability. Must be one of: ${validCapabilities.join(', ')}`);
|
|
7069
|
+
}
|
|
7070
|
+
}
|
|
7071
|
+
|
|
6653
7072
|
async run() {
|
|
6654
7073
|
const transport = new StdioServerTransport();
|
|
6655
7074
|
await this.server.connect(transport);
|
|
6656
7075
|
console.error('FrameworkMCP server running on stdio');
|
|
7076
|
+
|
|
7077
|
+
// Log performance stats every 5 minutes in production
|
|
7078
|
+
if (process.env.NODE_ENV === 'production') {
|
|
7079
|
+
setInterval(() => {
|
|
7080
|
+
console.error(`[FrameworkMCP] ${this.getPerformanceStats()}`);
|
|
7081
|
+
}, 5 * 60 * 1000);
|
|
7082
|
+
}
|
|
6657
7083
|
}
|
|
6658
7084
|
}
|
|
6659
7085
|
|