framework-mcp 1.1.2 → 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 +34 -35
- package/RELEASE_NOTES_v1.1.3.md +321 -0
- package/dist/index.d.ts +25 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +596 -403
- package/dist/index.js.map +1 -1
- package/package.json +3 -2
- package/src/index.ts +705 -461
- 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/dist/index.js
CHANGED
|
@@ -7,27 +7,27 @@ const SAFEGUARD_DOMAIN_REQUIREMENTS = {
|
|
|
7
7
|
"1.1": {
|
|
8
8
|
domain: "Asset Inventory",
|
|
9
9
|
required_tool_types: ["inventory", "asset_management", "cmdb", "discovery"],
|
|
10
|
-
description: "Only asset inventory and discovery tools can provide FULL/PARTIAL
|
|
10
|
+
description: "Only asset inventory and discovery tools can provide FULL/PARTIAL implementation capability"
|
|
11
11
|
},
|
|
12
12
|
"1.2": {
|
|
13
13
|
domain: "Asset Management",
|
|
14
14
|
required_tool_types: ["inventory", "asset_management", "network_security", "nac"],
|
|
15
|
-
description: "Asset management or network access control tools required for FULL/PARTIAL"
|
|
15
|
+
description: "Asset management or network access control tools required for FULL/PARTIAL implementation capability"
|
|
16
16
|
},
|
|
17
17
|
"5.1": {
|
|
18
18
|
domain: "Account Management",
|
|
19
19
|
required_tool_types: ["identity_management", "iam", "directory", "account_management"],
|
|
20
|
-
description: "Identity and account management tools required for FULL/PARTIAL"
|
|
20
|
+
description: "Identity and account management tools required for FULL/PARTIAL implementation capability"
|
|
21
21
|
},
|
|
22
22
|
"6.3": {
|
|
23
23
|
domain: "Authentication",
|
|
24
24
|
required_tool_types: ["mfa", "authentication", "identity_management", "iam"],
|
|
25
|
-
description: "Multi-factor authentication and identity tools required for FULL/PARTIAL"
|
|
25
|
+
description: "Multi-factor authentication and identity tools required for FULL/PARTIAL implementation capability"
|
|
26
26
|
},
|
|
27
27
|
"7.1": {
|
|
28
28
|
domain: "Vulnerability Management",
|
|
29
29
|
required_tool_types: ["vulnerability_management", "vulnerability_scanner", "patch_management"],
|
|
30
|
-
description: "Vulnerability management and scanning tools required for FULL/PARTIAL"
|
|
30
|
+
description: "Vulnerability management and scanning tools required for FULL/PARTIAL implementation capability"
|
|
31
31
|
}
|
|
32
32
|
};
|
|
33
33
|
// Enhanced CIS Controls Framework Data with color-coded categorization
|
|
@@ -5462,6 +5462,19 @@ const CIS_SAFEGUARDS = {
|
|
|
5462
5462
|
};
|
|
5463
5463
|
export class GRCAnalysisServer {
|
|
5464
5464
|
constructor() {
|
|
5465
|
+
// Performance monitoring and caching
|
|
5466
|
+
this.performanceMetrics = {
|
|
5467
|
+
toolExecutionTimes: new Map(),
|
|
5468
|
+
startTime: Date.now(),
|
|
5469
|
+
totalRequests: 0,
|
|
5470
|
+
errorCount: 0
|
|
5471
|
+
};
|
|
5472
|
+
// Simple cache for safeguard details (most commonly requested data)
|
|
5473
|
+
this.cache = {
|
|
5474
|
+
safeguardDetails: new Map(),
|
|
5475
|
+
safeguardList: null,
|
|
5476
|
+
lastCacheCleanup: Date.now()
|
|
5477
|
+
};
|
|
5465
5478
|
this.server = new Server({
|
|
5466
5479
|
name: 'framework-mcp',
|
|
5467
5480
|
version: '1.0.0',
|
|
@@ -5473,7 +5486,7 @@ export class GRCAnalysisServer {
|
|
|
5473
5486
|
tools: [
|
|
5474
5487
|
{
|
|
5475
5488
|
name: 'analyze_vendor_response',
|
|
5476
|
-
description: 'Analyze a vendor response
|
|
5489
|
+
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',
|
|
5477
5490
|
inputSchema: {
|
|
5478
5491
|
type: 'object',
|
|
5479
5492
|
properties: {
|
|
@@ -5488,7 +5501,7 @@ export class GRCAnalysisServer {
|
|
|
5488
5501
|
},
|
|
5489
5502
|
response_text: {
|
|
5490
5503
|
type: 'string',
|
|
5491
|
-
description: 'Vendor response text
|
|
5504
|
+
description: 'Vendor response text describing their tool capabilities for the safeguard'
|
|
5492
5505
|
}
|
|
5493
5506
|
},
|
|
5494
5507
|
required: ['vendor_name', 'safeguard_id', 'response_text']
|
|
@@ -5516,7 +5529,7 @@ export class GRCAnalysisServer {
|
|
|
5516
5529
|
},
|
|
5517
5530
|
{
|
|
5518
5531
|
name: 'validate_coverage_claim',
|
|
5519
|
-
description: 'Validate a vendor\'s
|
|
5532
|
+
description: 'Validate a vendor\'s implementation capability claim (FULL/PARTIAL) against specific safeguard requirements and evidence quality',
|
|
5520
5533
|
inputSchema: {
|
|
5521
5534
|
type: 'object',
|
|
5522
5535
|
properties: {
|
|
@@ -5532,16 +5545,16 @@ export class GRCAnalysisServer {
|
|
|
5532
5545
|
coverage_claim: {
|
|
5533
5546
|
type: 'string',
|
|
5534
5547
|
enum: ['FULL', 'PARTIAL'],
|
|
5535
|
-
description: 'Vendor\'s
|
|
5548
|
+
description: 'Vendor\'s implementation capability claim (FULL = complete implementation, PARTIAL = limited scope implementation)'
|
|
5536
5549
|
},
|
|
5537
5550
|
response_text: {
|
|
5538
5551
|
type: 'string',
|
|
5539
|
-
description: 'Vendor response explaining their
|
|
5552
|
+
description: 'Vendor response explaining their implementation capabilities'
|
|
5540
5553
|
},
|
|
5541
5554
|
capabilities: {
|
|
5542
5555
|
type: 'array',
|
|
5543
5556
|
items: { type: 'string' },
|
|
5544
|
-
description: 'List of vendor
|
|
5557
|
+
description: 'List of additional vendor capability types (Governance, Facilitates, Validates)'
|
|
5545
5558
|
}
|
|
5546
5559
|
},
|
|
5547
5560
|
required: ['vendor_name', 'safeguard_id', 'coverage_claim', 'response_text', 'capabilities']
|
|
@@ -5568,7 +5581,7 @@ export class GRCAnalysisServer {
|
|
|
5568
5581
|
},
|
|
5569
5582
|
{
|
|
5570
5583
|
name: 'validate_vendor_mapping',
|
|
5571
|
-
description: 'Validate whether a vendor\'s
|
|
5584
|
+
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',
|
|
5572
5585
|
inputSchema: {
|
|
5573
5586
|
type: 'object',
|
|
5574
5587
|
properties: {
|
|
@@ -5585,11 +5598,11 @@ export class GRCAnalysisServer {
|
|
|
5585
5598
|
claimed_capability: {
|
|
5586
5599
|
type: 'string',
|
|
5587
5600
|
enum: ['full', 'partial', 'facilitates', 'governance', 'validates'],
|
|
5588
|
-
description: 'Vendor\'s claimed capability
|
|
5601
|
+
description: 'Vendor\'s claimed capability role: full (complete implementation), partial (limited implementation), facilitates (enables/enhances), governance (policies/processes), validates (evidence/reporting)'
|
|
5589
5602
|
},
|
|
5590
5603
|
supporting_text: {
|
|
5591
5604
|
type: 'string',
|
|
5592
|
-
description: 'Vendor\'s supporting
|
|
5605
|
+
description: 'Vendor\'s supporting evidence explaining how their tool fulfills the claimed capability role'
|
|
5593
5606
|
}
|
|
5594
5607
|
},
|
|
5595
5608
|
required: ['safeguard_id', 'claimed_capability', 'supporting_text']
|
|
@@ -5599,28 +5612,45 @@ export class GRCAnalysisServer {
|
|
|
5599
5612
|
}));
|
|
5600
5613
|
this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
5601
5614
|
const { name, arguments: args } = request.params;
|
|
5615
|
+
const startTime = Date.now();
|
|
5602
5616
|
try {
|
|
5617
|
+
let result;
|
|
5603
5618
|
switch (name) {
|
|
5604
5619
|
case 'analyze_vendor_response':
|
|
5605
|
-
|
|
5620
|
+
result = await this.analyzeVendorResponse(args);
|
|
5621
|
+
break;
|
|
5606
5622
|
case 'get_safeguard_details':
|
|
5607
|
-
|
|
5623
|
+
result = await this.getSafeguardDetails(args);
|
|
5624
|
+
break;
|
|
5608
5625
|
case 'validate_coverage_claim':
|
|
5609
|
-
|
|
5626
|
+
result = await this.validateCoverageClaim(args);
|
|
5627
|
+
break;
|
|
5610
5628
|
case 'list_available_safeguards':
|
|
5611
|
-
|
|
5629
|
+
result = await this.listAvailableSafeguards(args);
|
|
5630
|
+
break;
|
|
5612
5631
|
case 'validate_vendor_mapping':
|
|
5613
|
-
|
|
5632
|
+
result = await this.validateVendorMapping(args);
|
|
5633
|
+
break;
|
|
5614
5634
|
default:
|
|
5615
5635
|
throw new Error(`Unknown tool: ${name}`);
|
|
5616
5636
|
}
|
|
5637
|
+
// Record successful execution time
|
|
5638
|
+
const executionTime = Date.now() - startTime;
|
|
5639
|
+
this.recordToolExecution(name, executionTime);
|
|
5640
|
+
return result;
|
|
5617
5641
|
}
|
|
5618
5642
|
catch (error) {
|
|
5643
|
+
// Record error and performance metrics
|
|
5644
|
+
this.performanceMetrics.errorCount++;
|
|
5645
|
+
const executionTime = Date.now() - startTime;
|
|
5646
|
+
this.recordToolExecution(`${name}_error`, executionTime);
|
|
5647
|
+
const errorMessage = this.formatErrorMessage(error, name);
|
|
5648
|
+
console.error(`[FrameworkMCP] Tool execution error: ${name}`, error);
|
|
5619
5649
|
return {
|
|
5620
5650
|
content: [
|
|
5621
5651
|
{
|
|
5622
5652
|
type: 'text',
|
|
5623
|
-
text:
|
|
5653
|
+
text: errorMessage,
|
|
5624
5654
|
},
|
|
5625
5655
|
],
|
|
5626
5656
|
};
|
|
@@ -5629,10 +5659,14 @@ export class GRCAnalysisServer {
|
|
|
5629
5659
|
}
|
|
5630
5660
|
async getSafeguardDetails(args) {
|
|
5631
5661
|
const { safeguard_id, include_examples = true } = args;
|
|
5632
|
-
|
|
5633
|
-
|
|
5634
|
-
|
|
5662
|
+
// Input validation
|
|
5663
|
+
this.validateSafeguardId(safeguard_id);
|
|
5664
|
+
// Check cache first
|
|
5665
|
+
const cached = this.getCachedSafeguardDetails(safeguard_id, include_examples);
|
|
5666
|
+
if (cached) {
|
|
5667
|
+
return cached;
|
|
5635
5668
|
}
|
|
5669
|
+
const safeguard = CIS_SAFEGUARDS[safeguard_id];
|
|
5636
5670
|
const result = {
|
|
5637
5671
|
...safeguard,
|
|
5638
5672
|
elementBreakdown: {
|
|
@@ -5660,7 +5694,7 @@ export class GRCAnalysisServer {
|
|
|
5660
5694
|
})
|
|
5661
5695
|
}
|
|
5662
5696
|
};
|
|
5663
|
-
|
|
5697
|
+
const response = {
|
|
5664
5698
|
content: [
|
|
5665
5699
|
{
|
|
5666
5700
|
type: 'text',
|
|
@@ -5668,9 +5702,19 @@ export class GRCAnalysisServer {
|
|
|
5668
5702
|
},
|
|
5669
5703
|
],
|
|
5670
5704
|
};
|
|
5705
|
+
// Cache the result for future requests
|
|
5706
|
+
this.setCachedSafeguardDetails(safeguard_id, include_examples, response);
|
|
5707
|
+
return response;
|
|
5671
5708
|
}
|
|
5672
5709
|
async listAvailableSafeguards(args) {
|
|
5673
5710
|
const { implementation_group, security_function } = args;
|
|
5711
|
+
// Check cache for complete safeguard list (only if no filters applied)
|
|
5712
|
+
if (!implementation_group && !security_function && this.cache.safeguardList) {
|
|
5713
|
+
const cacheAge = Date.now() - this.cache.safeguardList.timestamp;
|
|
5714
|
+
if (cacheAge < 10 * 60 * 1000) { // 10 minute cache for safeguard list
|
|
5715
|
+
return this.cache.safeguardList.data;
|
|
5716
|
+
}
|
|
5717
|
+
}
|
|
5674
5718
|
let safeguards = Object.values(CIS_SAFEGUARDS);
|
|
5675
5719
|
if (implementation_group) {
|
|
5676
5720
|
safeguards = safeguards.filter(s => s.implementationGroup === implementation_group);
|
|
@@ -5693,7 +5737,7 @@ export class GRCAnalysisServer {
|
|
|
5693
5737
|
securityFunction: s.securityFunction
|
|
5694
5738
|
}))
|
|
5695
5739
|
};
|
|
5696
|
-
|
|
5740
|
+
const response = {
|
|
5697
5741
|
content: [
|
|
5698
5742
|
{
|
|
5699
5743
|
type: 'text',
|
|
@@ -5701,14 +5745,25 @@ export class GRCAnalysisServer {
|
|
|
5701
5745
|
},
|
|
5702
5746
|
],
|
|
5703
5747
|
};
|
|
5748
|
+
// Cache the complete list if no filters were applied
|
|
5749
|
+
if (!implementation_group && !security_function) {
|
|
5750
|
+
this.cache.safeguardList = {
|
|
5751
|
+
data: response,
|
|
5752
|
+
timestamp: Date.now()
|
|
5753
|
+
};
|
|
5754
|
+
}
|
|
5755
|
+
return response;
|
|
5704
5756
|
}
|
|
5705
5757
|
async analyzeVendorResponse(args) {
|
|
5706
5758
|
const { vendor_name, safeguard_id, response_text } = args;
|
|
5707
|
-
|
|
5708
|
-
|
|
5709
|
-
|
|
5759
|
+
// Input validation
|
|
5760
|
+
this.validateSafeguardId(safeguard_id);
|
|
5761
|
+
this.validateTextInput(response_text, 'Response text');
|
|
5762
|
+
if (!vendor_name || typeof vendor_name !== 'string' || vendor_name.trim().length === 0) {
|
|
5763
|
+
throw new Error('Vendor name is required');
|
|
5710
5764
|
}
|
|
5711
|
-
const
|
|
5765
|
+
const safeguard = CIS_SAFEGUARDS[safeguard_id];
|
|
5766
|
+
const analysis = this.performCapabilityAnalysis(vendor_name, safeguard, response_text);
|
|
5712
5767
|
return {
|
|
5713
5768
|
content: [
|
|
5714
5769
|
{
|
|
@@ -5724,7 +5779,7 @@ export class GRCAnalysisServer {
|
|
|
5724
5779
|
if (!safeguard) {
|
|
5725
5780
|
throw new Error(`Safeguard ${safeguard_id} not found`);
|
|
5726
5781
|
}
|
|
5727
|
-
const analysis = this.
|
|
5782
|
+
const analysis = this.performCapabilityAnalysis(vendor_name, safeguard, response_text);
|
|
5728
5783
|
// Validate the coverage claim
|
|
5729
5784
|
const validation = this.validateClaim(coverage_claim, analysis, capabilities, safeguard);
|
|
5730
5785
|
return {
|
|
@@ -5743,163 +5798,242 @@ export class GRCAnalysisServer {
|
|
|
5743
5798
|
],
|
|
5744
5799
|
};
|
|
5745
5800
|
}
|
|
5746
|
-
|
|
5801
|
+
performCapabilityAnalysis(vendorName, safeguard, responseText) {
|
|
5747
5802
|
const text = responseText.toLowerCase();
|
|
5748
|
-
//
|
|
5749
|
-
const
|
|
5803
|
+
// Step 1: Determine what type of capability this tool is claiming
|
|
5804
|
+
const claimedCapability = this.determineClaimedCapability(text, safeguard);
|
|
5805
|
+
// Step 2: Assess how well the tool executes that specific capability type
|
|
5806
|
+
const qualityAssessment = this.assessCapabilityQuality(text, safeguard, claimedCapability);
|
|
5807
|
+
// Step 3: Generate capability-focused analysis
|
|
5808
|
+
return this.generateCapabilityAnalysis(vendorName, safeguard, responseText, claimedCapability, qualityAssessment);
|
|
5809
|
+
}
|
|
5810
|
+
determineClaimedCapability(text, safeguard) {
|
|
5811
|
+
// Capability detection keywords - focused on what the tool DOES, not what elements it covers
|
|
5812
|
+
const governanceIndicators = [
|
|
5750
5813
|
'policy', 'policies', 'manage', 'process', 'workflow', 'governance', 'grc',
|
|
5751
5814
|
'compliance management', 'documented', 'establish', 'maintain', 'procedure',
|
|
5752
5815
|
'control', 'controls', 'framework', 'standard', 'enterprise risk management',
|
|
5753
5816
|
'centralized management', 'oversight'
|
|
5754
5817
|
];
|
|
5755
|
-
const
|
|
5756
|
-
// Technical facilitation (original keywords)
|
|
5818
|
+
const facilitatesIndicators = [
|
|
5757
5819
|
'improve', 'enhance', 'optimize', 'faster', 'better', 'stronger', 'automate',
|
|
5758
5820
|
'streamline', 'efficiency', 'facilitate', 'support', 'enable', 'accelerate',
|
|
5759
5821
|
'api', 'integration', 'data', 'export', 'import', 'sync', 'feed',
|
|
5760
|
-
// Data provision and enrichment
|
|
5761
5822
|
'provides data', 'data source', 'data feeds', 'enrichment', 'data enrichment',
|
|
5762
5823
|
'supplemental data', 'additional data', 'contextual data', 'threat data',
|
|
5763
5824
|
'intelligence feeds', 'data aggregation', 'data collection', 'data gathering',
|
|
5764
5825
|
'feeds data', 'populates', 'informs', 'enriches', 'supplements',
|
|
5765
|
-
// Governance/process facilitation (new keywords for tools like Upolicy)
|
|
5766
5826
|
'enables compliance', 'facilitates implementation', 'supports compliance',
|
|
5767
5827
|
'creates framework', 'enables organizations', 'infrastructure', 'foundation',
|
|
5768
|
-
'compliance infrastructure', 'audit infrastructure', 'policy framework',
|
|
5769
|
-
'enables effective', 'working together', 'comprehensive coverage',
|
|
5770
5828
|
'template', 'templates', 'workflow automation', 'orchestration'
|
|
5771
5829
|
];
|
|
5772
|
-
const
|
|
5830
|
+
const validatesIndicators = [
|
|
5773
5831
|
'audit', 'report', 'evidence', 'verify', 'validate', 'check', 'monitor',
|
|
5774
5832
|
'compliance', 'compliance report', 'assessment', 'logging', 'tracking', 'review', 'attest',
|
|
5775
5833
|
'dashboard', 'metrics', 'analytics', 'visibility', 'alert', 'attestation',
|
|
5776
5834
|
'compliance tracking', 'audit trail', 'reporting capabilities', 'audit capabilities'
|
|
5777
5835
|
];
|
|
5778
|
-
//
|
|
5779
|
-
const
|
|
5780
|
-
|
|
5781
|
-
const
|
|
5782
|
-
const
|
|
5783
|
-
|
|
5784
|
-
const
|
|
5785
|
-
|
|
5786
|
-
|
|
5787
|
-
|
|
5788
|
-
|
|
5789
|
-
const validatesCapability = validatesScore > 0.3;
|
|
5790
|
-
// Check for specific facilitation patterns (tools that enable/support compliance)
|
|
5791
|
-
const facilitationPatterns = [
|
|
5792
|
-
'enables compliance', 'facilitates implementation', 'creates framework',
|
|
5793
|
-
'policy framework', 'compliance infrastructure', 'audit infrastructure',
|
|
5794
|
-
'enables organizations', 'enables effective', 'working together',
|
|
5795
|
-
'creates the policy framework', 'enables organizations to implement',
|
|
5796
|
-
'facilitates implementation of', 'compliance infrastructure facilitates'
|
|
5797
|
-
];
|
|
5798
|
-
const hasFacilitationPattern = facilitationPatterns.some(pattern => text.includes(pattern));
|
|
5799
|
-
// Check for explicit non-implementation language
|
|
5800
|
-
const nonImplementationPatterns = [
|
|
5801
|
-
'don\'t scan', 'don\'t catalog', 'doesn\'t scan', 'doesn\'t catalog',
|
|
5802
|
-
'not scan', 'not catalog', 'even though we don\'t', 'we don\'t directly',
|
|
5803
|
-
'rather than direct', 'instead of direct'
|
|
5804
|
-
];
|
|
5805
|
-
const hasNonImplementationLanguage = nonImplementationPatterns.some(pattern => text.includes(pattern));
|
|
5806
|
-
// Determine if full or partial coverage (based on core + sub-taxonomical elements WITHIN SCOPE)
|
|
5807
|
-
// Full = addresses majority of core requirements + substantial sub-elements within their stated scope
|
|
5808
|
-
// Partial = addresses some core requirements with clear scope boundaries
|
|
5809
|
-
const corePercentage = safeguard.coreRequirements.length > 0 ?
|
|
5810
|
-
(coreCoverage.coveredElements.length / safeguard.coreRequirements.length) * 100 : 0;
|
|
5811
|
-
const subElementPercentage = safeguard.subTaxonomicalElements.length > 0 ?
|
|
5812
|
-
(subElementCoverage.coveredElements.length / safeguard.subTaxonomicalElements.length) * 100 : 0;
|
|
5813
|
-
let fullCapability = false;
|
|
5814
|
-
let partialCapability = false;
|
|
5815
|
-
// Full capability: High coverage of core requirements + reasonable sub-element coverage
|
|
5816
|
-
if (corePercentage >= 70 && subElementPercentage >= 50) {
|
|
5817
|
-
fullCapability = true;
|
|
5836
|
+
// Direct implementation indicators (tools that actually perform the safeguard)
|
|
5837
|
+
const implementationIndicators = this.getImplementationIndicators(safeguard.id);
|
|
5838
|
+
// Calculate keyword presence scores
|
|
5839
|
+
const governanceScore = this.calculateKeywordScore(text, governanceIndicators);
|
|
5840
|
+
const facilitatesScore = this.calculateKeywordScore(text, facilitatesIndicators);
|
|
5841
|
+
const validatesScore = this.calculateKeywordScore(text, validatesIndicators);
|
|
5842
|
+
const implementationScore = this.calculateKeywordScore(text, implementationIndicators);
|
|
5843
|
+
// Determine claimed capability based on strongest indicators and patterns
|
|
5844
|
+
if (implementationScore > 0.2 && implementationScore >= Math.max(facilitatesScore, governanceScore, validatesScore)) {
|
|
5845
|
+
// Tool claims to directly implement the safeguard
|
|
5846
|
+
return implementationScore > 0.5 ? 'full' : 'partial';
|
|
5818
5847
|
}
|
|
5819
|
-
|
|
5820
|
-
|
|
5821
|
-
partialCapability = true;
|
|
5848
|
+
else if (governanceScore > 0.2 && governanceScore >= Math.max(facilitatesScore, validatesScore)) {
|
|
5849
|
+
return 'governance';
|
|
5822
5850
|
}
|
|
5823
|
-
|
|
5824
|
-
|
|
5825
|
-
if (fullCapability) {
|
|
5826
|
-
primaryCapability = 'full';
|
|
5851
|
+
else if (validatesScore > 0.2 && validatesScore >= facilitatesScore) {
|
|
5852
|
+
return 'validates';
|
|
5827
5853
|
}
|
|
5828
|
-
else
|
|
5829
|
-
|
|
5830
|
-
// Prioritize facilitation when:
|
|
5831
|
-
// 1. Clear facilitation language patterns detected, OR
|
|
5832
|
-
// 2. Explicit non-implementation language (tool doesn't directly implement), OR
|
|
5833
|
-
// 3. Facilitates score is substantial AND significantly higher than governance
|
|
5834
|
-
primaryCapability = 'facilitates';
|
|
5854
|
+
else {
|
|
5855
|
+
return 'facilitates';
|
|
5835
5856
|
}
|
|
5836
|
-
|
|
5837
|
-
|
|
5857
|
+
}
|
|
5858
|
+
getImplementationIndicators(safeguardId) {
|
|
5859
|
+
// Return specific indicators for what constitutes direct implementation for each safeguard
|
|
5860
|
+
const implementationMap = {
|
|
5861
|
+
"1.1": ['inventory', 'discovery', 'asset management', 'catalog', 'enumerate', 'scan devices', 'device database'],
|
|
5862
|
+
"1.2": ['unauthorized', 'rogue', 'detect', 'identify unauthorized', 'quarantine', 'block unauthorized'],
|
|
5863
|
+
"5.1": ['account inventory', 'user management', 'identity management', 'account lifecycle', 'user provisioning'],
|
|
5864
|
+
"6.3": ['multi-factor', 'mfa', '2fa', 'authentication', 'two-factor', 'multi-factor authentication'],
|
|
5865
|
+
"7.1": ['vulnerability', 'vuln', 'scanning', 'vulnerability management', 'security testing', 'penetration testing']
|
|
5866
|
+
};
|
|
5867
|
+
return implementationMap[safeguardId] || [];
|
|
5868
|
+
}
|
|
5869
|
+
assessCapabilityQuality(text, safeguard, claimedCapability) {
|
|
5870
|
+
// Assess how well the tool executes the claimed capability type
|
|
5871
|
+
const evidence = [];
|
|
5872
|
+
const gaps = [];
|
|
5873
|
+
// Quality assessment based on capability type
|
|
5874
|
+
let qualityScore = 0;
|
|
5875
|
+
switch (claimedCapability) {
|
|
5876
|
+
case 'full':
|
|
5877
|
+
case 'partial':
|
|
5878
|
+
qualityScore = this.assessImplementationQuality(text, safeguard, evidence, gaps);
|
|
5879
|
+
break;
|
|
5880
|
+
case 'governance':
|
|
5881
|
+
qualityScore = this.assessGovernanceQuality(text, safeguard, evidence, gaps);
|
|
5882
|
+
break;
|
|
5883
|
+
case 'facilitates':
|
|
5884
|
+
qualityScore = this.assessFacilitationQuality(text, safeguard, evidence, gaps);
|
|
5885
|
+
break;
|
|
5886
|
+
case 'validates':
|
|
5887
|
+
qualityScore = this.assessValidationQuality(text, safeguard, evidence, gaps);
|
|
5888
|
+
break;
|
|
5838
5889
|
}
|
|
5839
|
-
|
|
5840
|
-
|
|
5841
|
-
|
|
5890
|
+
// Convert score to quality rating
|
|
5891
|
+
let quality;
|
|
5892
|
+
if (qualityScore >= 0.8)
|
|
5893
|
+
quality = 'excellent';
|
|
5894
|
+
else if (qualityScore >= 0.6)
|
|
5895
|
+
quality = 'good';
|
|
5896
|
+
else if (qualityScore >= 0.4)
|
|
5897
|
+
quality = 'fair';
|
|
5898
|
+
else
|
|
5899
|
+
quality = 'poor';
|
|
5900
|
+
return {
|
|
5901
|
+
quality,
|
|
5902
|
+
confidence: Math.round(qualityScore * 100),
|
|
5903
|
+
evidence: evidence.slice(0, 5), // Top 5 pieces of evidence
|
|
5904
|
+
gaps: gaps.slice(0, 3) // Top 3 gaps identified
|
|
5905
|
+
};
|
|
5906
|
+
}
|
|
5907
|
+
assessImplementationQuality(text, safeguard, evidence, gaps) {
|
|
5908
|
+
// Assess quality of direct implementation capability
|
|
5909
|
+
const implementationIndicators = this.getImplementationIndicators(safeguard.id);
|
|
5910
|
+
let score = 0;
|
|
5911
|
+
// Check for strong implementation language
|
|
5912
|
+
const strongIndicators = implementationIndicators.filter(indicator => text.includes(indicator.toLowerCase()));
|
|
5913
|
+
if (strongIndicators.length > 0) {
|
|
5914
|
+
score += 0.4;
|
|
5915
|
+
evidence.push(`Strong implementation indicators: ${strongIndicators.join(', ')}`);
|
|
5842
5916
|
}
|
|
5843
|
-
|
|
5844
|
-
|
|
5845
|
-
|
|
5917
|
+
// Check for comprehensive functionality description
|
|
5918
|
+
if (text.includes('comprehensive') || text.includes('complete') || text.includes('full')) {
|
|
5919
|
+
score += 0.2;
|
|
5920
|
+
evidence.push('Claims comprehensive functionality');
|
|
5846
5921
|
}
|
|
5847
|
-
|
|
5848
|
-
|
|
5849
|
-
|
|
5922
|
+
// Check for automated vs manual implementation
|
|
5923
|
+
if (text.includes('automat') || text.includes('real-time') || text.includes('continuous')) {
|
|
5924
|
+
score += 0.2;
|
|
5925
|
+
evidence.push('Automated implementation capability');
|
|
5926
|
+
}
|
|
5927
|
+
// Identify potential gaps
|
|
5928
|
+
if (strongIndicators.length === 0) {
|
|
5929
|
+
gaps.push('No clear implementation indicators found');
|
|
5930
|
+
}
|
|
5931
|
+
return Math.min(score, 1.0);
|
|
5932
|
+
}
|
|
5933
|
+
assessGovernanceQuality(text, safeguard, evidence, gaps) {
|
|
5934
|
+
const governanceIndicators = ['policy', 'process', 'governance', 'compliance', 'documentation', 'oversight'];
|
|
5935
|
+
let score = 0;
|
|
5936
|
+
const foundIndicators = governanceIndicators.filter(indicator => text.includes(indicator));
|
|
5937
|
+
if (foundIndicators.length >= 3) {
|
|
5938
|
+
score += 0.5;
|
|
5939
|
+
evidence.push(`Strong governance capability: ${foundIndicators.join(', ')}`);
|
|
5940
|
+
}
|
|
5941
|
+
if (text.includes('documented') && text.includes('process')) {
|
|
5942
|
+
score += 0.3;
|
|
5943
|
+
evidence.push('Documented process management');
|
|
5944
|
+
}
|
|
5945
|
+
return Math.min(score, 1.0);
|
|
5946
|
+
}
|
|
5947
|
+
assessFacilitationQuality(text, safeguard, evidence, gaps) {
|
|
5948
|
+
const facilitationIndicators = ['enhance', 'enable', 'support', 'facilitate', 'improve', 'optimize'];
|
|
5949
|
+
let score = 0;
|
|
5950
|
+
const foundIndicators = facilitationIndicators.filter(indicator => text.includes(indicator));
|
|
5951
|
+
if (foundIndicators.length >= 2) {
|
|
5952
|
+
score += 0.4;
|
|
5953
|
+
evidence.push(`Clear facilitation capability: ${foundIndicators.join(', ')}`);
|
|
5850
5954
|
}
|
|
5851
|
-
|
|
5852
|
-
|
|
5853
|
-
|
|
5955
|
+
return Math.min(score, 1.0);
|
|
5956
|
+
}
|
|
5957
|
+
assessValidationQuality(text, safeguard, evidence, gaps) {
|
|
5958
|
+
const validationIndicators = ['audit', 'report', 'monitor', 'track', 'verify', 'validate'];
|
|
5959
|
+
let score = 0;
|
|
5960
|
+
const foundIndicators = validationIndicators.filter(indicator => text.includes(indicator));
|
|
5961
|
+
if (foundIndicators.length >= 2) {
|
|
5962
|
+
score += 0.4;
|
|
5963
|
+
evidence.push(`Strong validation capability: ${foundIndicators.join(', ')}`);
|
|
5854
5964
|
}
|
|
5855
|
-
|
|
5856
|
-
|
|
5857
|
-
|
|
5858
|
-
|
|
5859
|
-
const totalCoreAndSubElements = safeguard.coreRequirements.length + safeguard.subTaxonomicalElements.length;
|
|
5860
|
-
const coveredCoreAndSubElements = coreCoverage.coveredElements.length + subElementCoverage.coveredElements.length;
|
|
5861
|
-
const coverageConfidence = totalCoreAndSubElements > 0 ?
|
|
5862
|
-
coveredCoreAndSubElements / totalCoreAndSubElements : 0;
|
|
5863
|
-
const confidence = Math.min((keywordConfidence * 0.4 + coverageConfidence * 0.6) * 100, 100);
|
|
5965
|
+
return Math.min(score, 1.0);
|
|
5966
|
+
}
|
|
5967
|
+
generateCapabilityAnalysis(vendorName, safeguard, responseText, claimedCapability, qualityAssessment) {
|
|
5968
|
+
// Generate the new capability-focused analysis result
|
|
5864
5969
|
return {
|
|
5865
5970
|
vendor: vendorName,
|
|
5866
5971
|
safeguardId: safeguard.id,
|
|
5867
5972
|
safeguardTitle: safeguard.title,
|
|
5868
|
-
capability:
|
|
5973
|
+
capability: claimedCapability,
|
|
5869
5974
|
capabilities: {
|
|
5870
|
-
full:
|
|
5871
|
-
partial:
|
|
5872
|
-
facilitates:
|
|
5873
|
-
governance:
|
|
5874
|
-
validates:
|
|
5975
|
+
full: claimedCapability === 'full',
|
|
5976
|
+
partial: claimedCapability === 'partial',
|
|
5977
|
+
facilitates: claimedCapability === 'facilitates',
|
|
5978
|
+
governance: claimedCapability === 'governance',
|
|
5979
|
+
validates: claimedCapability === 'validates'
|
|
5875
5980
|
},
|
|
5876
|
-
confidence:
|
|
5877
|
-
reasoning: this.generateCapabilityReasoning(
|
|
5878
|
-
evidence,
|
|
5879
|
-
|
|
5880
|
-
|
|
5881
|
-
|
|
5882
|
-
|
|
5883
|
-
|
|
5884
|
-
|
|
5885
|
-
|
|
5886
|
-
|
|
5887
|
-
|
|
5888
|
-
|
|
5981
|
+
confidence: qualityAssessment.confidence,
|
|
5982
|
+
reasoning: this.generateCapabilityReasoning(claimedCapability, qualityAssessment, safeguard),
|
|
5983
|
+
evidence: qualityAssessment.evidence,
|
|
5984
|
+
// Note: elementsCovered is now less relevant in capability-focused analysis
|
|
5985
|
+
// We focus on tool capability rather than element coverage
|
|
5986
|
+
toolCapabilityDescription: this.generateToolCapabilityDescription(claimedCapability, qualityAssessment),
|
|
5987
|
+
recommendedUse: this.generateRecommendedUse(claimedCapability, safeguard)
|
|
5988
|
+
};
|
|
5989
|
+
}
|
|
5990
|
+
generateCapabilityReasoning(claimedCapability, qualityAssessment, safeguard) {
|
|
5991
|
+
const capabilityDescriptions = {
|
|
5992
|
+
full: "directly implements the core functionality of this safeguard",
|
|
5993
|
+
partial: "implements limited aspects of this safeguard with clear scope boundaries",
|
|
5994
|
+
facilitates: "enhances or enables the implementation of this safeguard by others",
|
|
5995
|
+
governance: "provides governance, policy, and oversight capabilities for this safeguard",
|
|
5996
|
+
validates: "provides evidence, audit, and compliance validation for this safeguard"
|
|
5997
|
+
};
|
|
5998
|
+
const qualityDescriptor = qualityAssessment.quality;
|
|
5999
|
+
const description = capabilityDescriptions[claimedCapability];
|
|
6000
|
+
return `This tool ${description} with ${qualityDescriptor} capability quality. ${qualityAssessment.evidence.length > 0 ? 'Evidence: ' + qualityAssessment.evidence.join('; ') : ''}`;
|
|
6001
|
+
}
|
|
6002
|
+
generateToolCapabilityDescription(claimedCapability, qualityAssessment) {
|
|
6003
|
+
const roleDescriptions = {
|
|
6004
|
+
full: "Core Implementation Tool - Directly performs the safeguard functionality",
|
|
6005
|
+
partial: "Focused Implementation Tool - Performs specific aspects of the safeguard",
|
|
6006
|
+
facilitates: "Enablement Tool - Helps organizations implement the safeguard more effectively",
|
|
6007
|
+
governance: "Governance Tool - Manages policies, processes, and oversight for the safeguard",
|
|
6008
|
+
validates: "Compliance Tool - Provides audit, evidence, and validation capabilities"
|
|
5889
6009
|
};
|
|
6010
|
+
return roleDescriptions[claimedCapability] || "Support Tool";
|
|
6011
|
+
}
|
|
6012
|
+
generateRecommendedUse(claimedCapability, safeguard) {
|
|
6013
|
+
const recommendations = {
|
|
6014
|
+
full: `Use as primary implementation tool for ${safeguard.title}. Ensure proper configuration and integration.`,
|
|
6015
|
+
partial: `Use as part of a multi-tool strategy for ${safeguard.title}. Supplement with additional capabilities as needed.`,
|
|
6016
|
+
facilitates: `Use to enhance existing safeguard implementation. Combine with direct implementation tools.`,
|
|
6017
|
+
governance: `Use for policy management and governance oversight. Pair with implementation and validation tools.`,
|
|
6018
|
+
validates: `Use for compliance monitoring and evidence collection. Combine with implementation tools for complete coverage.`
|
|
6019
|
+
};
|
|
6020
|
+
return recommendations[claimedCapability] || "Evaluate specific use case alignment.";
|
|
5890
6021
|
}
|
|
5891
6022
|
calculateKeywordScore(text, keywords) {
|
|
5892
|
-
let
|
|
5893
|
-
let
|
|
6023
|
+
let matchedKeywords = 0;
|
|
6024
|
+
let totalMatches = 0;
|
|
5894
6025
|
keywords.forEach(keyword => {
|
|
5895
6026
|
const regex = new RegExp(keyword.replace(/\s+/g, '\\s+'), 'gi');
|
|
5896
6027
|
const keywordMatches = (text.match(regex) || []).length;
|
|
5897
6028
|
if (keywordMatches > 0) {
|
|
5898
|
-
|
|
5899
|
-
|
|
6029
|
+
matchedKeywords++;
|
|
6030
|
+
totalMatches += keywordMatches;
|
|
5900
6031
|
}
|
|
5901
6032
|
});
|
|
5902
|
-
|
|
6033
|
+
// Return percentage of keywords that were found, with bonus for multiple matches
|
|
6034
|
+
const baseScore = matchedKeywords / keywords.length;
|
|
6035
|
+
const matchBonus = Math.min(totalMatches * 0.1, 0.5); // Up to 50% bonus for multiple matches
|
|
6036
|
+
return Math.min(baseScore + matchBonus, 1.0);
|
|
5903
6037
|
}
|
|
5904
6038
|
analyzeElementCoverage(text, elements) {
|
|
5905
6039
|
const coveredElements = [];
|
|
@@ -6009,63 +6143,6 @@ export class GRCAnalysisServer {
|
|
|
6009
6143
|
}
|
|
6010
6144
|
return reasons.join('. ');
|
|
6011
6145
|
}
|
|
6012
|
-
generateCapabilityReasoning(primaryCapability, full, partial, governance, facilitates, validates, coreCoverage, subElementCoverage, safeguard, hasFacilitationPattern = false, hasNonImplementationLanguage = false) {
|
|
6013
|
-
const reasons = [];
|
|
6014
|
-
// Primary capability explanation
|
|
6015
|
-
switch (primaryCapability) {
|
|
6016
|
-
case 'full':
|
|
6017
|
-
reasons.push(`Provides FULL coverage of ${safeguard.title} - directly implements all core and sub-taxonomical elements`);
|
|
6018
|
-
break;
|
|
6019
|
-
case 'partial':
|
|
6020
|
-
reasons.push(`Provides PARTIAL coverage of ${safeguard.title} - directly implements some but not all core and sub-taxonomical elements`);
|
|
6021
|
-
break;
|
|
6022
|
-
case 'facilitates':
|
|
6023
|
-
if (hasFacilitationPattern || hasNonImplementationLanguage || governance) {
|
|
6024
|
-
reasons.push(`FACILITATES ${safeguard.title} by creating governance frameworks, policy infrastructure, and compliance processes that enable organizations to implement the control effectively`);
|
|
6025
|
-
}
|
|
6026
|
-
else {
|
|
6027
|
-
reasons.push(`FACILITATES ${safeguard.title} through data integration, automation, or technical capabilities that support implementation`);
|
|
6028
|
-
}
|
|
6029
|
-
break;
|
|
6030
|
-
case 'governance':
|
|
6031
|
-
reasons.push(`Provides GOVERNANCE capabilities for ${safeguard.title} through centralized policy management, process controls, and compliance oversight`);
|
|
6032
|
-
break;
|
|
6033
|
-
case 'validates':
|
|
6034
|
-
reasons.push(`VALIDATES ${safeguard.title} implementation through evidence collection, compliance reporting, and audit capabilities`);
|
|
6035
|
-
break;
|
|
6036
|
-
default:
|
|
6037
|
-
reasons.push(`No clear capability identified for ${safeguard.title}`);
|
|
6038
|
-
}
|
|
6039
|
-
// Coverage details
|
|
6040
|
-
if (coreCoverage.coveredElements.length > 0) {
|
|
6041
|
-
reasons.push(`Core elements addressed: ${coreCoverage.coveredElements.length}/${safeguard.coreRequirements.length}`);
|
|
6042
|
-
}
|
|
6043
|
-
if (subElementCoverage.coveredElements.length > 0) {
|
|
6044
|
-
reasons.push(`Sub-taxonomical elements addressed: ${subElementCoverage.coveredElements.length}/${safeguard.subTaxonomicalElements.length}`);
|
|
6045
|
-
}
|
|
6046
|
-
// Additional context for facilitation tools
|
|
6047
|
-
if (primaryCapability === 'facilitates') {
|
|
6048
|
-
if (hasFacilitationPattern || hasNonImplementationLanguage || governance) {
|
|
6049
|
-
reasons.push(`Note: This type of facilitation tool works alongside technical implementation solutions (asset scanners, MDM tools, etc.) to provide comprehensive control coverage`);
|
|
6050
|
-
}
|
|
6051
|
-
if (hasNonImplementationLanguage) {
|
|
6052
|
-
reasons.push(`Tool explicitly enables compliance through governance/process rather than direct technical implementation`);
|
|
6053
|
-
}
|
|
6054
|
-
}
|
|
6055
|
-
// Multi-capability products
|
|
6056
|
-
const capabilityFlags = [governance, facilitates, validates].filter(Boolean);
|
|
6057
|
-
if (capabilityFlags.length > 1) {
|
|
6058
|
-
const capabilities = [];
|
|
6059
|
-
if (governance)
|
|
6060
|
-
capabilities.push('governance');
|
|
6061
|
-
if (facilitates)
|
|
6062
|
-
capabilities.push('facilitates');
|
|
6063
|
-
if (validates)
|
|
6064
|
-
capabilities.push('validates');
|
|
6065
|
-
reasons.push(`Multi-capability product with: ${capabilities.join(', ')}`);
|
|
6066
|
-
}
|
|
6067
|
-
return reasons.join('. ');
|
|
6068
|
-
}
|
|
6069
6146
|
validateClaim(claim, analysis, capabilities, safeguard) {
|
|
6070
6147
|
const validation = {
|
|
6071
6148
|
coverageClaimValid: false,
|
|
@@ -6078,16 +6155,14 @@ export class GRCAnalysisServer {
|
|
|
6078
6155
|
const meetsFullCriteria = analysis.capabilities.full;
|
|
6079
6156
|
validation.coverageClaimValid = meetsFullCriteria;
|
|
6080
6157
|
if (!meetsFullCriteria) {
|
|
6081
|
-
|
|
6082
|
-
const coveredElements = analysis.elementsCovered.coreRequirements.length + analysis.elementsCovered.subTaxonomicalElements.length;
|
|
6083
|
-
validation.gaps.push(`FULL coverage claim not supported: Only ${coveredElements}/${totalElements} core and sub-taxonomical elements covered`);
|
|
6158
|
+
validation.gaps.push(`FULL implementation capability claim not supported: Tool does not demonstrate direct implementation of core safeguard functionality`);
|
|
6084
6159
|
}
|
|
6085
6160
|
}
|
|
6086
6161
|
else if (claim === 'PARTIAL') {
|
|
6087
6162
|
const meetsPartialCriteria = analysis.capabilities.partial || analysis.capabilities.full;
|
|
6088
6163
|
validation.coverageClaimValid = meetsPartialCriteria;
|
|
6089
6164
|
if (!meetsPartialCriteria) {
|
|
6090
|
-
validation.gaps.push(`PARTIAL
|
|
6165
|
+
validation.gaps.push(`PARTIAL implementation capability claim questionable: No core or sub-taxonomical elements clearly addressed`);
|
|
6091
6166
|
}
|
|
6092
6167
|
}
|
|
6093
6168
|
// Validate capability claims
|
|
@@ -6131,12 +6206,18 @@ export class GRCAnalysisServer {
|
|
|
6131
6206
|
}
|
|
6132
6207
|
else {
|
|
6133
6208
|
validation.recommendations.push(`Consider requesting additional information about: ${validation.gaps.join(', ')}`);
|
|
6134
|
-
//
|
|
6135
|
-
if (analysis.
|
|
6136
|
-
validation.recommendations.push(
|
|
6209
|
+
// Capability-based recommendations
|
|
6210
|
+
if (analysis.capability === 'facilitates') {
|
|
6211
|
+
validation.recommendations.push('Consider pairing with direct implementation tools for complete safeguard coverage');
|
|
6212
|
+
}
|
|
6213
|
+
else if (analysis.capability === 'partial') {
|
|
6214
|
+
validation.recommendations.push('Evaluate scope limitations and identify complementary tools for full coverage');
|
|
6215
|
+
}
|
|
6216
|
+
else if (analysis.capability === 'governance') {
|
|
6217
|
+
validation.recommendations.push('Combine with technical implementation tools for complete safeguard execution');
|
|
6137
6218
|
}
|
|
6138
|
-
if (analysis.
|
|
6139
|
-
validation.recommendations.push(
|
|
6219
|
+
else if (analysis.capability === 'validates') {
|
|
6220
|
+
validation.recommendations.push('Pair with implementation tools to ensure both execution and validation coverage');
|
|
6140
6221
|
}
|
|
6141
6222
|
if (!analysis.capabilities.validates && capabilities.includes('Validates')) {
|
|
6142
6223
|
validation.recommendations.push(`Request examples of audit trails, reporting capabilities, and compliance evidence`);
|
|
@@ -6146,10 +6227,11 @@ export class GRCAnalysisServer {
|
|
|
6146
6227
|
}
|
|
6147
6228
|
async validateVendorMapping(args) {
|
|
6148
6229
|
const { vendor_name = 'Unknown Vendor', safeguard_id, claimed_capability, supporting_text } = args;
|
|
6230
|
+
// Input validation
|
|
6231
|
+
this.validateSafeguardId(safeguard_id);
|
|
6232
|
+
this.validateTextInput(supporting_text, 'Supporting text');
|
|
6233
|
+
this.validateCapability(claimed_capability);
|
|
6149
6234
|
const safeguard = CIS_SAFEGUARDS[safeguard_id];
|
|
6150
|
-
if (!safeguard) {
|
|
6151
|
-
throw new Error(`Safeguard ${safeguard_id} not found. Available safeguards: ${Object.keys(CIS_SAFEGUARDS).join(', ')}`);
|
|
6152
|
-
}
|
|
6153
6235
|
const validation = this.validateCapabilityClaim(vendor_name, safeguard, claimed_capability, supporting_text);
|
|
6154
6236
|
return {
|
|
6155
6237
|
content: [
|
|
@@ -6163,7 +6245,7 @@ export class GRCAnalysisServer {
|
|
|
6163
6245
|
validateCapabilityClaim(vendorName, safeguard, claimedCapability, supportingText) {
|
|
6164
6246
|
const text = supportingText.toLowerCase();
|
|
6165
6247
|
// Detect tool type and validate domain match
|
|
6166
|
-
const detectedToolType = this.detectToolType(supportingText);
|
|
6248
|
+
const detectedToolType = this.detectToolType(supportingText, safeguard.id);
|
|
6167
6249
|
const domainValidation = this.validateDomainMatch(safeguard.id, claimedCapability, detectedToolType);
|
|
6168
6250
|
// Adjust capability if domain mismatch detected
|
|
6169
6251
|
let effectiveCapability = claimedCapability;
|
|
@@ -6172,20 +6254,10 @@ export class GRCAnalysisServer {
|
|
|
6172
6254
|
originalClaim = claimedCapability;
|
|
6173
6255
|
effectiveCapability = domainValidation.adjusted_capability;
|
|
6174
6256
|
}
|
|
6175
|
-
// Perform
|
|
6176
|
-
const actualAnalysis = this.
|
|
6177
|
-
//
|
|
6178
|
-
const
|
|
6179
|
-
const subElementCoverage = this.analyzeBinaryElementCoverage(text, safeguard.subTaxonomicalElements);
|
|
6180
|
-
const governanceCoverage = this.analyzeBinaryElementCoverage(text, safeguard.governanceElements);
|
|
6181
|
-
const corePercentage = safeguard.coreRequirements.length > 0 ?
|
|
6182
|
-
(coreCoverage.coveredElements.length / safeguard.coreRequirements.length) * 100 : 0;
|
|
6183
|
-
const subElementPercentage = safeguard.subTaxonomicalElements.length > 0 ?
|
|
6184
|
-
(subElementCoverage.coveredElements.length / safeguard.subTaxonomicalElements.length) * 100 : 0;
|
|
6185
|
-
const governancePercentage = safeguard.governanceElements.length > 0 ?
|
|
6186
|
-
(governanceCoverage.coveredElements.length / safeguard.governanceElements.length) * 100 : 0;
|
|
6187
|
-
// Validate claim against criteria (using effective capability after domain adjustment)
|
|
6188
|
-
const validation = this.assessClaimAlignment(effectiveCapability, actualAnalysis, corePercentage, subElementPercentage, governancePercentage, text);
|
|
6257
|
+
// Perform capability-focused analysis of the supporting text
|
|
6258
|
+
const actualAnalysis = this.performCapabilityAnalysis(vendorName, safeguard, supportingText);
|
|
6259
|
+
// Validate claimed capability against actual capability analysis and domain requirements
|
|
6260
|
+
const validation = this.assessCapabilityClaimAlignment(claimedCapability, effectiveCapability, actualAnalysis, domainValidation, text);
|
|
6189
6261
|
// Add domain validation gaps if capability was adjusted
|
|
6190
6262
|
if (domainValidation.should_adjust_capability) {
|
|
6191
6263
|
validation.gaps.unshift(`Domain mismatch: ${domainValidation.reasoning}`);
|
|
@@ -6200,12 +6272,10 @@ export class GRCAnalysisServer {
|
|
|
6200
6272
|
claimed_capability: claimedCapability,
|
|
6201
6273
|
validation_status: validation.status,
|
|
6202
6274
|
confidence_score: validation.confidence,
|
|
6203
|
-
|
|
6204
|
-
|
|
6205
|
-
|
|
6206
|
-
|
|
6207
|
-
language_consistency: validation.languageConsistency
|
|
6208
|
-
},
|
|
6275
|
+
actual_capability_detected: actualAnalysis.capability,
|
|
6276
|
+
capability_confidence: actualAnalysis.confidence,
|
|
6277
|
+
tool_capability_description: actualAnalysis.toolCapabilityDescription,
|
|
6278
|
+
recommended_use: actualAnalysis.recommendedUse,
|
|
6209
6279
|
domain_validation: {
|
|
6210
6280
|
required_tool_type: domainValidation.required_tool_types.join('/'),
|
|
6211
6281
|
detected_tool_type: detectedToolType,
|
|
@@ -6219,112 +6289,42 @@ export class GRCAnalysisServer {
|
|
|
6219
6289
|
detailed_feedback: validation.feedback
|
|
6220
6290
|
};
|
|
6221
6291
|
}
|
|
6222
|
-
|
|
6292
|
+
assessCapabilityClaimAlignment(claimedCapability, effectiveCapability, actualAnalysis, domainValidation, text) {
|
|
6223
6293
|
const gaps = [];
|
|
6224
6294
|
const strengths = [];
|
|
6225
6295
|
const recommendations = [];
|
|
6226
|
-
|
|
6296
|
+
// Compare claimed capability with what we actually detected
|
|
6297
|
+
const claimedLower = claimedCapability.toLowerCase();
|
|
6298
|
+
const effectiveLower = effectiveCapability.toLowerCase();
|
|
6299
|
+
const actualCapability = actualAnalysis.capability;
|
|
6227
6300
|
let alignmentScore = 0;
|
|
6228
|
-
|
|
6229
|
-
|
|
6230
|
-
|
|
6231
|
-
|
|
6232
|
-
|
|
6233
|
-
|
|
6234
|
-
|
|
6235
|
-
|
|
6236
|
-
|
|
6237
|
-
|
|
6238
|
-
|
|
6239
|
-
|
|
6240
|
-
|
|
6241
|
-
|
|
6242
|
-
|
|
6243
|
-
|
|
6244
|
-
|
|
6245
|
-
|
|
6246
|
-
|
|
6247
|
-
|
|
6248
|
-
|
|
6249
|
-
|
|
6250
|
-
|
|
6251
|
-
|
|
6252
|
-
|
|
6253
|
-
break;
|
|
6254
|
-
case 'partial':
|
|
6255
|
-
// Validate PARTIAL claim
|
|
6256
|
-
if (corePercentage >= 30 || (corePercentage > 0 && subElementPercentage >= 20)) {
|
|
6257
|
-
alignmentScore = 75;
|
|
6258
|
-
strengths.push('Appropriate coverage level for PARTIAL implementation');
|
|
6259
|
-
}
|
|
6260
|
-
else {
|
|
6261
|
-
alignmentScore = Math.max(0, corePercentage + subElementPercentage - 10);
|
|
6262
|
-
gaps.push(`Coverage too low even for PARTIAL claim: ${Math.round(corePercentage)}% core, ${Math.round(subElementPercentage)}% sub-elements`);
|
|
6263
|
-
}
|
|
6264
|
-
// Check for scope boundary definition
|
|
6265
|
-
if (this.hasScopeBoundaries(text)) {
|
|
6266
|
-
strengths.push('Clearly defines scope boundaries and limitations');
|
|
6267
|
-
alignmentScore += 10;
|
|
6268
|
-
}
|
|
6269
|
-
else {
|
|
6270
|
-
gaps.push('Should clearly define scope boundaries for PARTIAL implementation');
|
|
6271
|
-
recommendations.push('Specify exactly which elements are covered and which are not');
|
|
6272
|
-
}
|
|
6273
|
-
languageConsistency = this.assessImplementationLanguage(text);
|
|
6274
|
-
break;
|
|
6275
|
-
case 'facilitates':
|
|
6276
|
-
// Validate FACILITATES claim
|
|
6277
|
-
if (this.hasFacilitationLanguage(text) || actualAnalysis.capabilities.facilitates) {
|
|
6278
|
-
alignmentScore = 80;
|
|
6279
|
-
strengths.push('Contains appropriate facilitation and enablement language');
|
|
6280
|
-
}
|
|
6281
|
-
else {
|
|
6282
|
-
alignmentScore = 40;
|
|
6283
|
-
gaps.push('Lacks clear facilitation language (enables, supports, provides framework)');
|
|
6284
|
-
}
|
|
6285
|
-
// Check that it doesn't claim direct implementation
|
|
6286
|
-
if (this.hasDirectImplementationLanguage(text)) {
|
|
6287
|
-
// Special handling: If it lacks facilitation language AND claims implementation, stay QUESTIONABLE
|
|
6288
|
-
if (alignmentScore <= 40) {
|
|
6289
|
-
alignmentScore = 45; // Keep it in QUESTIONABLE range
|
|
6290
|
-
}
|
|
6291
|
-
else {
|
|
6292
|
-
alignmentScore -= 15;
|
|
6293
|
-
}
|
|
6294
|
-
gaps.push('Claims direct implementation, inconsistent with FACILITATES capability');
|
|
6295
|
-
}
|
|
6296
|
-
languageConsistency = this.assessFacilitationLanguage(text);
|
|
6297
|
-
break;
|
|
6298
|
-
case 'governance':
|
|
6299
|
-
// Validate GOVERNANCE claim
|
|
6300
|
-
if (governancePercentage >= 60 || actualAnalysis.capabilities.governance) {
|
|
6301
|
-
alignmentScore = 85;
|
|
6302
|
-
strengths.push('Strong governance element coverage and policy management language');
|
|
6303
|
-
}
|
|
6304
|
-
else {
|
|
6305
|
-
alignmentScore = Math.max(30, governancePercentage);
|
|
6306
|
-
gaps.push(`Governance element coverage (${Math.round(governancePercentage)}%) below expected threshold (60%)`);
|
|
6307
|
-
}
|
|
6308
|
-
languageConsistency = this.assessGovernanceLanguage(text);
|
|
6309
|
-
break;
|
|
6310
|
-
case 'validates':
|
|
6311
|
-
// Validate VALIDATES claim
|
|
6312
|
-
if (actualAnalysis.capabilities.validates) {
|
|
6313
|
-
alignmentScore = 85;
|
|
6314
|
-
strengths.push('Contains evidence collection and reporting capabilities');
|
|
6315
|
-
}
|
|
6316
|
-
else {
|
|
6317
|
-
alignmentScore = 30;
|
|
6318
|
-
gaps.push('Lacks validation language (audit, report, evidence, verify, monitor)');
|
|
6319
|
-
}
|
|
6320
|
-
languageConsistency = this.assessValidationLanguage(text);
|
|
6321
|
-
break;
|
|
6322
|
-
default:
|
|
6323
|
-
alignmentScore = 0;
|
|
6324
|
-
gaps.push(`Unknown capability type: ${claimedCapability}`);
|
|
6325
|
-
languageConsistency = 0;
|
|
6301
|
+
// Check if claim aligns with actual analysis
|
|
6302
|
+
if (claimedLower === actualCapability) {
|
|
6303
|
+
alignmentScore = actualAnalysis.confidence;
|
|
6304
|
+
strengths.push(`Claimed capability '${claimedCapability}' aligns with detected capability`);
|
|
6305
|
+
strengths.push(`Tool demonstrates appropriate ${actualAnalysis.toolCapabilityDescription.toLowerCase()}`);
|
|
6306
|
+
}
|
|
6307
|
+
else if (effectiveLower === actualCapability) {
|
|
6308
|
+
// Domain validation adjusted the capability and it matches the analysis
|
|
6309
|
+
alignmentScore = Math.max(actualAnalysis.confidence - 20, 30);
|
|
6310
|
+
gaps.push(`Original claim '${claimedCapability}' doesn't match tool type, adjusted to '${effectiveCapability}'`);
|
|
6311
|
+
strengths.push(`Adjusted capability '${effectiveCapability}' aligns with tool analysis`);
|
|
6312
|
+
}
|
|
6313
|
+
else {
|
|
6314
|
+
// Neither claimed nor effective capability matches the analysis
|
|
6315
|
+
alignmentScore = Math.max(actualAnalysis.confidence - 40, 10);
|
|
6316
|
+
gaps.push(`Claimed capability '${claimedCapability}' doesn't align with detected capability '${actualCapability}'`);
|
|
6317
|
+
gaps.push(`Tool appears to be: ${actualAnalysis.toolCapabilityDescription}`);
|
|
6318
|
+
}
|
|
6319
|
+
// Add evidence from the capability analysis
|
|
6320
|
+
if (actualAnalysis.evidence && actualAnalysis.evidence.length > 0) {
|
|
6321
|
+
strengths.push(`Supporting evidence: ${actualAnalysis.evidence.slice(0, 2).join('; ')}`);
|
|
6322
|
+
}
|
|
6323
|
+
// Domain validation feedback
|
|
6324
|
+
if (!domainValidation.domain_match) {
|
|
6325
|
+
gaps.push(`Tool type '${domainValidation.detected_tool_type}' not appropriate for this safeguard domain`);
|
|
6326
6326
|
}
|
|
6327
|
-
// Determine overall status
|
|
6327
|
+
// Determine overall status based on alignment score
|
|
6328
6328
|
let status;
|
|
6329
6329
|
if (alignmentScore >= 70) {
|
|
6330
6330
|
status = 'SUPPORTED';
|
|
@@ -6335,18 +6335,18 @@ export class GRCAnalysisServer {
|
|
|
6335
6335
|
else {
|
|
6336
6336
|
status = 'UNSUPPORTED';
|
|
6337
6337
|
}
|
|
6338
|
-
// Generate recommendations
|
|
6339
|
-
|
|
6340
|
-
recommendations.push('Address identified gaps to strengthen capability claim');
|
|
6341
|
-
}
|
|
6338
|
+
// Generate capability-focused recommendations
|
|
6339
|
+
recommendations.push(actualAnalysis.recommendedUse);
|
|
6342
6340
|
if (status === 'QUESTIONABLE') {
|
|
6343
|
-
recommendations.push('
|
|
6341
|
+
recommendations.push('Consider clarifying tool capabilities or adjusting capability claim');
|
|
6344
6342
|
}
|
|
6345
|
-
|
|
6343
|
+
if (!domainValidation.domain_match) {
|
|
6344
|
+
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`);
|
|
6345
|
+
}
|
|
6346
|
+
const feedback = this.generateCapabilityValidationFeedback(claimedCapability, effectiveCapability, actualCapability, status, alignmentScore, domainValidation);
|
|
6346
6347
|
return {
|
|
6347
6348
|
status,
|
|
6348
6349
|
confidence: Math.round(alignmentScore),
|
|
6349
|
-
languageConsistency: Math.round(languageConsistency),
|
|
6350
6350
|
gaps,
|
|
6351
6351
|
strengths,
|
|
6352
6352
|
recommendations,
|
|
@@ -6404,70 +6404,139 @@ export class GRCAnalysisServer {
|
|
|
6404
6404
|
];
|
|
6405
6405
|
return this.calculateKeywordScore(text, validationKeywords) * 100;
|
|
6406
6406
|
}
|
|
6407
|
-
detectToolType(text) {
|
|
6407
|
+
detectToolType(text, safeguardId) {
|
|
6408
6408
|
const lowerText = text.toLowerCase();
|
|
6409
|
-
//
|
|
6410
|
-
const
|
|
6411
|
-
'
|
|
6412
|
-
|
|
6413
|
-
|
|
6414
|
-
|
|
6415
|
-
|
|
6416
|
-
|
|
6417
|
-
|
|
6418
|
-
|
|
6419
|
-
|
|
6420
|
-
|
|
6421
|
-
|
|
6422
|
-
|
|
6423
|
-
'
|
|
6424
|
-
|
|
6425
|
-
|
|
6426
|
-
|
|
6427
|
-
|
|
6428
|
-
|
|
6429
|
-
|
|
6430
|
-
|
|
6431
|
-
|
|
6432
|
-
|
|
6433
|
-
|
|
6434
|
-
|
|
6435
|
-
'
|
|
6436
|
-
|
|
6437
|
-
|
|
6438
|
-
|
|
6439
|
-
|
|
6440
|
-
|
|
6441
|
-
|
|
6442
|
-
|
|
6443
|
-
|
|
6444
|
-
|
|
6445
|
-
|
|
6446
|
-
'
|
|
6447
|
-
|
|
6448
|
-
|
|
6449
|
-
|
|
6450
|
-
|
|
6451
|
-
|
|
6452
|
-
|
|
6453
|
-
|
|
6454
|
-
|
|
6455
|
-
|
|
6456
|
-
|
|
6457
|
-
|
|
6458
|
-
|
|
6459
|
-
|
|
6460
|
-
|
|
6461
|
-
|
|
6462
|
-
|
|
6409
|
+
// Enhanced keyword definitions with scoring weights and context
|
|
6410
|
+
const toolTypePatterns = {
|
|
6411
|
+
'inventory': {
|
|
6412
|
+
primary: [
|
|
6413
|
+
'asset management', 'inventory management', 'cmdb', 'configuration management database',
|
|
6414
|
+
'asset discovery', 'hardware inventory', 'software inventory', 'device inventory',
|
|
6415
|
+
'asset tracking', 'it asset management', 'endpoint discovery', 'asset lifecycle'
|
|
6416
|
+
],
|
|
6417
|
+
secondary: [
|
|
6418
|
+
'inventory', 'discovery', 'device management', 'endpoint management',
|
|
6419
|
+
'configuration management', 'asset database', 'equipment tracking'
|
|
6420
|
+
],
|
|
6421
|
+
weight: { primary: 3, secondary: 1 }
|
|
6422
|
+
},
|
|
6423
|
+
'identity_management': {
|
|
6424
|
+
primary: [
|
|
6425
|
+
'identity management', 'iam', 'active directory', 'identity provider',
|
|
6426
|
+
'single sign-on', 'sso', 'multi-factor authentication', 'mfa',
|
|
6427
|
+
'user management', 'account management', 'directory service'
|
|
6428
|
+
],
|
|
6429
|
+
secondary: [
|
|
6430
|
+
'ldap', 'authentication', 'access management', 'identity access management',
|
|
6431
|
+
'user directory', 'account lifecycle', 'privileged access'
|
|
6432
|
+
],
|
|
6433
|
+
weight: { primary: 3, secondary: 1 }
|
|
6434
|
+
},
|
|
6435
|
+
'vulnerability_management': {
|
|
6436
|
+
primary: [
|
|
6437
|
+
'vulnerability management', 'vulnerability scanner', 'patch management',
|
|
6438
|
+
'security scanning', 'vulnerability assessment', 'penetration testing'
|
|
6439
|
+
],
|
|
6440
|
+
secondary: [
|
|
6441
|
+
'vuln scan', 'security scanner', 'network scanner', 'scanning capabilities',
|
|
6442
|
+
'security assessment', 'vulnerability scanning', 'patch deployment'
|
|
6443
|
+
],
|
|
6444
|
+
weight: { primary: 3, secondary: 1 }
|
|
6445
|
+
},
|
|
6446
|
+
'threat_intelligence': {
|
|
6447
|
+
primary: [
|
|
6448
|
+
'threat intelligence', 'cyber threat intelligence', 'threat intel',
|
|
6449
|
+
'threat feed', 'ioc feed', 'security intelligence', 'threat data'
|
|
6450
|
+
],
|
|
6451
|
+
secondary: [
|
|
6452
|
+
'enrichment', 'data feed', 'contextual data', 'risk intelligence',
|
|
6453
|
+
'threat indicators', 'intelligence platform', 'threat correlation'
|
|
6454
|
+
],
|
|
6455
|
+
weight: { primary: 3, secondary: 1 }
|
|
6456
|
+
},
|
|
6457
|
+
'network_security': {
|
|
6458
|
+
primary: [
|
|
6459
|
+
'firewall', 'network access control', 'nac', 'intrusion detection',
|
|
6460
|
+
'network security', 'network segmentation'
|
|
6461
|
+
],
|
|
6462
|
+
secondary: [
|
|
6463
|
+
'network monitoring', 'traffic analysis', 'perimeter security',
|
|
6464
|
+
'network protection', 'network filtering'
|
|
6465
|
+
],
|
|
6466
|
+
weight: { primary: 3, secondary: 1 }
|
|
6467
|
+
},
|
|
6468
|
+
'governance': {
|
|
6469
|
+
primary: [
|
|
6470
|
+
'grc', 'governance risk compliance', 'compliance management',
|
|
6471
|
+
'policy management', 'risk management', 'audit management'
|
|
6472
|
+
],
|
|
6473
|
+
secondary: [
|
|
6474
|
+
'governance', 'compliance platform', 'policy enforcement',
|
|
6475
|
+
'regulatory compliance', 'framework management'
|
|
6476
|
+
],
|
|
6477
|
+
weight: { primary: 3, secondary: 1 }
|
|
6478
|
+
},
|
|
6479
|
+
'security_analytics': {
|
|
6480
|
+
primary: [
|
|
6481
|
+
'siem', 'security information event management', 'security analytics',
|
|
6482
|
+
'soar', 'security orchestration', 'log management'
|
|
6483
|
+
],
|
|
6484
|
+
secondary: [
|
|
6485
|
+
'security monitoring', 'event correlation', 'log analysis',
|
|
6486
|
+
'security intelligence', 'incident response platform'
|
|
6487
|
+
],
|
|
6488
|
+
weight: { primary: 3, secondary: 1 }
|
|
6489
|
+
}
|
|
6490
|
+
};
|
|
6491
|
+
// Calculate scores for each tool type
|
|
6492
|
+
const toolScores = {};
|
|
6493
|
+
for (const [toolType, patterns] of Object.entries(toolTypePatterns)) {
|
|
6494
|
+
let score = 0;
|
|
6495
|
+
// Check primary keywords
|
|
6496
|
+
for (const keyword of patterns.primary) {
|
|
6497
|
+
if (lowerText.includes(keyword)) {
|
|
6498
|
+
score += patterns.weight.primary;
|
|
6499
|
+
}
|
|
6500
|
+
}
|
|
6501
|
+
// Check secondary keywords
|
|
6502
|
+
for (const keyword of patterns.secondary) {
|
|
6503
|
+
if (lowerText.includes(keyword)) {
|
|
6504
|
+
score += patterns.weight.secondary;
|
|
6505
|
+
}
|
|
6506
|
+
}
|
|
6507
|
+
toolScores[toolType] = score;
|
|
6463
6508
|
}
|
|
6464
|
-
|
|
6465
|
-
|
|
6509
|
+
// Apply safeguard-specific context weighting if provided
|
|
6510
|
+
if (safeguardId && toolScores) {
|
|
6511
|
+
const contextBonus = 1; // Small bonus for domain alignment
|
|
6512
|
+
// Asset inventory safeguards (1.1, 1.2) favor inventory tools
|
|
6513
|
+
if (['1.1', '1.2'].includes(safeguardId) && toolScores['inventory'] > 0) {
|
|
6514
|
+
toolScores['inventory'] += contextBonus;
|
|
6515
|
+
}
|
|
6516
|
+
// Account inventory safeguards (5.1, 5.2, 5.3) favor identity tools
|
|
6517
|
+
if (['5.1', '5.2', '5.3'].includes(safeguardId) && toolScores['identity_management'] > 0) {
|
|
6518
|
+
toolScores['identity_management'] += contextBonus;
|
|
6519
|
+
}
|
|
6520
|
+
// Authentication safeguards (6.1, 6.2, 6.3) favor identity tools
|
|
6521
|
+
if (['6.1', '6.2', '6.3'].includes(safeguardId) && toolScores['identity_management'] > 0) {
|
|
6522
|
+
toolScores['identity_management'] += contextBonus;
|
|
6523
|
+
}
|
|
6524
|
+
// Vulnerability safeguards (7.1-7.7) favor vulnerability management tools
|
|
6525
|
+
if (['7.1', '7.2', '7.3', '7.4', '7.5', '7.6', '7.7'].includes(safeguardId) && toolScores['vulnerability_management'] > 0) {
|
|
6526
|
+
toolScores['vulnerability_management'] += contextBonus;
|
|
6527
|
+
}
|
|
6466
6528
|
}
|
|
6467
|
-
|
|
6468
|
-
|
|
6529
|
+
// Find the tool type with highest score
|
|
6530
|
+
let maxScore = 0;
|
|
6531
|
+
let detectedType = 'unknown';
|
|
6532
|
+
for (const [toolType, score] of Object.entries(toolScores)) {
|
|
6533
|
+
if (score > maxScore) {
|
|
6534
|
+
maxScore = score;
|
|
6535
|
+
detectedType = toolType;
|
|
6536
|
+
}
|
|
6469
6537
|
}
|
|
6470
|
-
|
|
6538
|
+
// Require minimum score threshold to avoid false positives
|
|
6539
|
+
return maxScore >= 2 ? detectedType : 'unknown';
|
|
6471
6540
|
}
|
|
6472
6541
|
validateDomainMatch(safeguardId, claimedCapability, detectedToolType) {
|
|
6473
6542
|
const domainReq = SAFEGUARD_DOMAIN_REQUIREMENTS[safeguardId];
|
|
@@ -6487,7 +6556,7 @@ export class GRCAnalysisServer {
|
|
|
6487
6556
|
required_tool_types: domainReq.required_tool_types,
|
|
6488
6557
|
should_adjust_capability: true,
|
|
6489
6558
|
adjusted_capability: 'facilitates',
|
|
6490
|
-
reasoning: `${domainReq.domain} safeguard requires ${domainReq.required_tool_types.join('/')} tool types for FULL/PARTIAL
|
|
6559
|
+
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.`
|
|
6491
6560
|
};
|
|
6492
6561
|
}
|
|
6493
6562
|
return {
|
|
@@ -6499,8 +6568,31 @@ export class GRCAnalysisServer {
|
|
|
6499
6568
|
'No domain validation required for this capability type'
|
|
6500
6569
|
};
|
|
6501
6570
|
}
|
|
6571
|
+
generateCapabilityValidationFeedback(claimedCapability, effectiveCapability, actualCapability, status, score, domainValidation) {
|
|
6572
|
+
let feedback = `Capability Validation: ${claimedCapability.toUpperCase()} claim is ${status} (${Math.round(score)}% confidence)\n\n`;
|
|
6573
|
+
// Analysis summary
|
|
6574
|
+
feedback += `ANALYSIS:\n`;
|
|
6575
|
+
feedback += `• Claimed: ${claimedCapability.toUpperCase()}\n`;
|
|
6576
|
+
if (effectiveCapability !== claimedCapability) {
|
|
6577
|
+
feedback += `• Domain Adjusted: ${effectiveCapability.toUpperCase()} (${domainValidation.reasoning})\n`;
|
|
6578
|
+
}
|
|
6579
|
+
feedback += `• Detected: ${actualCapability.toUpperCase()}\n`;
|
|
6580
|
+
feedback += `• Tool Type: ${domainValidation.detected_tool_type}\n\n`;
|
|
6581
|
+
// Assessment
|
|
6582
|
+
feedback += `ASSESSMENT: `;
|
|
6583
|
+
if (claimedCapability.toLowerCase() === actualCapability) {
|
|
6584
|
+
feedback += 'Claimed capability aligns perfectly with tool analysis.';
|
|
6585
|
+
}
|
|
6586
|
+
else if (effectiveCapability.toLowerCase() === actualCapability) {
|
|
6587
|
+
feedback += 'After domain validation adjustment, capability aligns with tool analysis.';
|
|
6588
|
+
}
|
|
6589
|
+
else {
|
|
6590
|
+
feedback += `Capability mismatch detected. Tool functions as ${actualCapability.toUpperCase()} rather than claimed ${claimedCapability.toUpperCase()}.`;
|
|
6591
|
+
}
|
|
6592
|
+
return feedback;
|
|
6593
|
+
}
|
|
6502
6594
|
generateValidationFeedback(claimedCapability, status, gaps, strengths, score) {
|
|
6503
|
-
let feedback = `Validation of ${claimedCapability.toUpperCase()} capability claim: ${status} (${Math.round(score)}% alignment)\n\n`;
|
|
6595
|
+
let feedback = `Validation of ${claimedCapability.toUpperCase()} capability role claim: ${status} (${Math.round(score)}% alignment)\n\n`;
|
|
6504
6596
|
if (strengths.length > 0) {
|
|
6505
6597
|
feedback += `STRENGTHS:\n${strengths.map(s => `• ${s}`).join('\n')}\n\n`;
|
|
6506
6598
|
}
|
|
@@ -6510,21 +6602,122 @@ export class GRCAnalysisServer {
|
|
|
6510
6602
|
feedback += `ASSESSMENT: `;
|
|
6511
6603
|
switch (status) {
|
|
6512
6604
|
case 'SUPPORTED':
|
|
6513
|
-
feedback += 'The vendor\'s supporting evidence strongly aligns with their claimed capability.';
|
|
6605
|
+
feedback += 'The vendor\'s supporting evidence strongly aligns with their claimed capability role.';
|
|
6514
6606
|
break;
|
|
6515
6607
|
case 'QUESTIONABLE':
|
|
6516
6608
|
feedback += 'The vendor\'s evidence partially supports their claim but has notable gaps or inconsistencies.';
|
|
6517
6609
|
break;
|
|
6518
6610
|
case 'UNSUPPORTED':
|
|
6519
|
-
feedback += 'The vendor\'s evidence does not adequately support their claimed capability.';
|
|
6611
|
+
feedback += 'The vendor\'s evidence does not adequately support their claimed capability role.';
|
|
6520
6612
|
break;
|
|
6521
6613
|
}
|
|
6522
6614
|
return feedback;
|
|
6523
6615
|
}
|
|
6616
|
+
// Enhanced error handling and formatting
|
|
6617
|
+
formatErrorMessage(error, toolName) {
|
|
6618
|
+
if (error instanceof Error) {
|
|
6619
|
+
// Production-friendly error messages
|
|
6620
|
+
switch (error.message) {
|
|
6621
|
+
case /^Safeguard .+ not found/.test(error.message) ? error.message : '':
|
|
6622
|
+
return `❌ Invalid safeguard ID. Use 'list_available_safeguards' to see available CIS Control safeguards.`;
|
|
6623
|
+
case /^Unknown tool/.test(error.message) ? error.message : '':
|
|
6624
|
+
return `❌ Tool '${toolName}' is not available. Available tools: analyze_vendor_response, validate_vendor_mapping, validate_coverage_claim, get_safeguard_details, list_available_safeguards.`;
|
|
6625
|
+
default:
|
|
6626
|
+
return `❌ Error in ${toolName}: ${error.message}`;
|
|
6627
|
+
}
|
|
6628
|
+
}
|
|
6629
|
+
return `❌ Unexpected error in ${toolName}: ${String(error)}`;
|
|
6630
|
+
}
|
|
6631
|
+
getCachedSafeguardDetails(safeguardId, includeExamples) {
|
|
6632
|
+
const cacheKey = `${safeguardId}_${includeExamples}`;
|
|
6633
|
+
const cached = this.cache.safeguardDetails.get(cacheKey);
|
|
6634
|
+
if (cached && (Date.now() - cached.timestamp < 5 * 60 * 1000)) { // 5 minute cache
|
|
6635
|
+
return cached.data;
|
|
6636
|
+
}
|
|
6637
|
+
return null;
|
|
6638
|
+
}
|
|
6639
|
+
setCachedSafeguardDetails(safeguardId, includeExamples, data) {
|
|
6640
|
+
const cacheKey = `${safeguardId}_${includeExamples}`;
|
|
6641
|
+
this.cache.safeguardDetails.set(cacheKey, {
|
|
6642
|
+
data,
|
|
6643
|
+
timestamp: Date.now()
|
|
6644
|
+
});
|
|
6645
|
+
// Periodic cache cleanup to prevent memory leaks
|
|
6646
|
+
if (Date.now() - this.cache.lastCacheCleanup > 10 * 60 * 1000) { // 10 minutes
|
|
6647
|
+
this.cleanupCache();
|
|
6648
|
+
}
|
|
6649
|
+
}
|
|
6650
|
+
cleanupCache() {
|
|
6651
|
+
const now = Date.now();
|
|
6652
|
+
const maxAge = 10 * 60 * 1000; // 10 minutes
|
|
6653
|
+
// Clean up safeguard details cache
|
|
6654
|
+
for (const [key, value] of this.cache.safeguardDetails.entries()) {
|
|
6655
|
+
if (now - value.timestamp > maxAge) {
|
|
6656
|
+
this.cache.safeguardDetails.delete(key);
|
|
6657
|
+
}
|
|
6658
|
+
}
|
|
6659
|
+
this.cache.lastCacheCleanup = now;
|
|
6660
|
+
}
|
|
6661
|
+
recordToolExecution(toolName, executionTime) {
|
|
6662
|
+
this.performanceMetrics.totalRequests++;
|
|
6663
|
+
if (!this.performanceMetrics.toolExecutionTimes.has(toolName)) {
|
|
6664
|
+
this.performanceMetrics.toolExecutionTimes.set(toolName, []);
|
|
6665
|
+
}
|
|
6666
|
+
const times = this.performanceMetrics.toolExecutionTimes.get(toolName);
|
|
6667
|
+
times.push(executionTime);
|
|
6668
|
+
// Keep only last 100 measurements for memory efficiency
|
|
6669
|
+
if (times.length > 100) {
|
|
6670
|
+
times.shift();
|
|
6671
|
+
}
|
|
6672
|
+
}
|
|
6673
|
+
getPerformanceStats() {
|
|
6674
|
+
const uptime = Date.now() - this.performanceMetrics.startTime;
|
|
6675
|
+
const avgTimes = Array.from(this.performanceMetrics.toolExecutionTimes.entries())
|
|
6676
|
+
.map(([tool, times]) => {
|
|
6677
|
+
const avg = times.reduce((a, b) => a + b, 0) / times.length;
|
|
6678
|
+
return `${tool}: ${avg.toFixed(2)}ms`;
|
|
6679
|
+
});
|
|
6680
|
+
return `Performance Stats (Uptime: ${(uptime / 1000).toFixed(1)}s, Requests: ${this.performanceMetrics.totalRequests}, Errors: ${this.performanceMetrics.errorCount})\n${avgTimes.join(', ')}`;
|
|
6681
|
+
}
|
|
6682
|
+
// Input validation and sanitization
|
|
6683
|
+
validateSafeguardId(safeguardId) {
|
|
6684
|
+
if (!safeguardId || typeof safeguardId !== 'string') {
|
|
6685
|
+
throw new Error('Safeguard ID is required and must be a string');
|
|
6686
|
+
}
|
|
6687
|
+
if (!/^[0-9]+\.[0-9]+$/.test(safeguardId)) {
|
|
6688
|
+
throw new Error('Safeguard ID must be in format "X.Y" (e.g., "1.1", "5.1")');
|
|
6689
|
+
}
|
|
6690
|
+
if (!CIS_SAFEGUARDS[safeguardId]) {
|
|
6691
|
+
throw new Error(`Safeguard ${safeguardId} not found`);
|
|
6692
|
+
}
|
|
6693
|
+
}
|
|
6694
|
+
validateTextInput(text, fieldName) {
|
|
6695
|
+
if (!text || typeof text !== 'string') {
|
|
6696
|
+
throw new Error(`${fieldName} is required and must be a string`);
|
|
6697
|
+
}
|
|
6698
|
+
if (text.length > 10000) {
|
|
6699
|
+
throw new Error(`${fieldName} must be less than 10,000 characters`);
|
|
6700
|
+
}
|
|
6701
|
+
if (text.trim().length < 10) {
|
|
6702
|
+
throw new Error(`${fieldName} must contain at least 10 meaningful characters`);
|
|
6703
|
+
}
|
|
6704
|
+
}
|
|
6705
|
+
validateCapability(capability) {
|
|
6706
|
+
const validCapabilities = ['full', 'partial', 'facilitates', 'governance', 'validates'];
|
|
6707
|
+
if (!validCapabilities.includes(capability.toLowerCase())) {
|
|
6708
|
+
throw new Error(`Invalid capability. Must be one of: ${validCapabilities.join(', ')}`);
|
|
6709
|
+
}
|
|
6710
|
+
}
|
|
6524
6711
|
async run() {
|
|
6525
6712
|
const transport = new StdioServerTransport();
|
|
6526
6713
|
await this.server.connect(transport);
|
|
6527
6714
|
console.error('FrameworkMCP server running on stdio');
|
|
6715
|
+
// Log performance stats every 5 minutes in production
|
|
6716
|
+
if (process.env.NODE_ENV === 'production') {
|
|
6717
|
+
setInterval(() => {
|
|
6718
|
+
console.error(`[FrameworkMCP] ${this.getPerformanceStats()}`);
|
|
6719
|
+
}, 5 * 60 * 1000);
|
|
6720
|
+
}
|
|
6528
6721
|
}
|
|
6529
6722
|
}
|
|
6530
6723
|
const server = new GRCAnalysisServer();
|