first
This commit is contained in:
320
quality-assurance-validation.js
Normal file
320
quality-assurance-validation.js
Normal file
@@ -0,0 +1,320 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
/**
|
||||
* Quality Assurance Validation Script
|
||||
* Validates HIPAA compliance, authentication requirements, and parameter accuracy
|
||||
*/
|
||||
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
|
||||
/**
|
||||
* Load API documentation and current endpoints
|
||||
*/
|
||||
function loadData() {
|
||||
try {
|
||||
// Load API documentation
|
||||
const apiDocsPath = path.join(process.cwd(), 'complete-api-parameters.json');
|
||||
const apiDocs = JSON.parse(fs.readFileSync(apiDocsPath, 'utf8'));
|
||||
|
||||
// Load current endpoints
|
||||
const endpointsPath = path.join(process.cwd(), 'src/config/endpoints.js');
|
||||
const endpointsContent = fs.readFileSync(endpointsPath, 'utf8');
|
||||
|
||||
return { apiDocs, endpointsContent };
|
||||
} catch (error) {
|
||||
console.error('❌ Error loading data:', error.message);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate HIPAA compliance categorization
|
||||
*/
|
||||
function validateHIPAACompliance(endpointsContent) {
|
||||
console.log('🏥 Validating HIPAA Compliance...\n');
|
||||
|
||||
const hipaaViolations = [];
|
||||
const clinicalPatterns = [
|
||||
'/emr/',
|
||||
'/patient/',
|
||||
'/medical',
|
||||
'/appointment',
|
||||
'/prescription',
|
||||
'/diagnosis',
|
||||
'/treatment',
|
||||
'/vitals',
|
||||
'/lab',
|
||||
'/document'
|
||||
];
|
||||
|
||||
// Check PUBLIC endpoints for potential HIPAA violations
|
||||
const publicMatch = endpointsContent.match(/export const PUBLIC_ENDPOINTS = \[([\s\S]*?)\];/);
|
||||
if (publicMatch) {
|
||||
const publicContent = publicMatch[1];
|
||||
|
||||
clinicalPatterns.forEach(pattern => {
|
||||
const regex = new RegExp(`path:\\s*["'][^"']*${pattern}[^"']*["']`, 'gi');
|
||||
const matches = publicContent.match(regex);
|
||||
|
||||
if (matches) {
|
||||
matches.forEach(match => {
|
||||
const pathMatch = match.match(/path:\s*["']([^"']+)["']/);
|
||||
if (pathMatch) {
|
||||
const path = pathMatch[1];
|
||||
// Allow certain public endpoints that are safe
|
||||
if (!path.includes('/login') && !path.includes('/register') && !path.includes('/forgot-password')) {
|
||||
hipaaViolations.push({
|
||||
type: 'HIPAA_VIOLATION',
|
||||
path,
|
||||
issue: `Clinical endpoint in PUBLIC category may violate HIPAA`,
|
||||
recommendation: 'Move to PROVIDER or PATIENT category'
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
console.log(`✅ HIPAA Compliance Check: ${hipaaViolations.length} potential violations found\n`);
|
||||
return hipaaViolations;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate authentication requirements
|
||||
*/
|
||||
function validateAuthentication(endpointsContent) {
|
||||
console.log('🔐 Validating Authentication Requirements...\n');
|
||||
|
||||
const authIssues = [];
|
||||
|
||||
// Check for sensitive endpoints in wrong categories
|
||||
const sensitivePatterns = {
|
||||
'/emr/': 'PROVIDER',
|
||||
'/admin/': 'ADMIN',
|
||||
'/patient/': 'PATIENT',
|
||||
'/partner/': 'PARTNER',
|
||||
'/affiliate/': 'AFFILIATE',
|
||||
'/network/': 'NETWORK'
|
||||
};
|
||||
|
||||
Object.entries(sensitivePatterns).forEach(([pattern, expectedAuth]) => {
|
||||
const regex = new RegExp(`export const PUBLIC_ENDPOINTS = \\[([\\s\\S]*?)\\];`);
|
||||
const publicMatch = endpointsContent.match(regex);
|
||||
|
||||
if (publicMatch) {
|
||||
const publicContent = publicMatch[1];
|
||||
const pathRegex = new RegExp(`path:\\s*["'][^"']*${pattern}[^"']*["']`, 'gi');
|
||||
const matches = publicContent.match(pathRegex);
|
||||
|
||||
if (matches) {
|
||||
matches.forEach(match => {
|
||||
const pathMatch = match.match(/path:\s*["']([^"']+)["']/);
|
||||
if (pathMatch) {
|
||||
const path = pathMatch[1];
|
||||
// Allow login/register endpoints
|
||||
if (!path.includes('/login') && !path.includes('/register')) {
|
||||
authIssues.push({
|
||||
type: 'AUTH_MISMATCH',
|
||||
path,
|
||||
currentAuth: 'PUBLIC',
|
||||
expectedAuth,
|
||||
issue: `Sensitive endpoint should require ${expectedAuth} authentication`
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
console.log(`✅ Authentication Validation: ${authIssues.length} issues found\n`);
|
||||
return authIssues;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate parameter accuracy
|
||||
*/
|
||||
function validateParameterAccuracy(apiDocs, endpointsContent) {
|
||||
console.log('📋 Validating Parameter Accuracy...\n');
|
||||
|
||||
const parameterIssues = [];
|
||||
let checkedEndpoints = 0;
|
||||
let accurateEndpoints = 0;
|
||||
|
||||
// Sample validation for key endpoints
|
||||
const keyEndpoints = apiDocs.filter(endpoint =>
|
||||
endpoint.path.includes('/emr/') ||
|
||||
endpoint.path.includes('/patient/') ||
|
||||
endpoint.path.includes('/appointment')
|
||||
).slice(0, 10); // Check first 10 for performance
|
||||
|
||||
keyEndpoints.forEach(apiEndpoint => {
|
||||
checkedEndpoints++;
|
||||
|
||||
// Find corresponding endpoint in configuration
|
||||
const pathRegex = new RegExp(`path:\\s*["']${apiEndpoint.path.replace(/[{}]/g, '\\$&')}["']`, 'g');
|
||||
const match = endpointsContent.match(pathRegex);
|
||||
|
||||
if (match) {
|
||||
// Extract parameter block for this endpoint
|
||||
const endpointRegex = new RegExp(
|
||||
`\\{[\\s\\S]*?path:\\s*["']${apiEndpoint.path.replace(/[{}]/g, '\\$&')}["'][\\s\\S]*?parameters:\\s*\\{([\\s\\S]*?)\\}[\\s\\S]*?\\}`,
|
||||
'g'
|
||||
);
|
||||
const endpointMatch = endpointsContent.match(endpointRegex);
|
||||
|
||||
if (endpointMatch) {
|
||||
const parametersText = endpointMatch[0];
|
||||
|
||||
// Check if API parameters are represented
|
||||
const apiParams = [
|
||||
...apiEndpoint.parameters.path,
|
||||
...apiEndpoint.parameters.query,
|
||||
...apiEndpoint.parameters.body
|
||||
];
|
||||
|
||||
let hasAllParams = true;
|
||||
const missingParams = [];
|
||||
|
||||
apiParams.forEach(param => {
|
||||
const paramRegex = new RegExp(`${param.name}:\\s*\\{`, 'g');
|
||||
if (!parametersText.match(paramRegex)) {
|
||||
hasAllParams = false;
|
||||
missingParams.push(param.name);
|
||||
}
|
||||
});
|
||||
|
||||
if (hasAllParams && apiParams.length > 0) {
|
||||
accurateEndpoints++;
|
||||
} else if (missingParams.length > 0) {
|
||||
parameterIssues.push({
|
||||
type: 'MISSING_PARAMETERS',
|
||||
path: apiEndpoint.path,
|
||||
missingParams,
|
||||
issue: `Missing parameters: ${missingParams.join(', ')}`
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const accuracy = checkedEndpoints > 0 ? ((accurateEndpoints / checkedEndpoints) * 100).toFixed(1) : 0;
|
||||
console.log(`✅ Parameter Accuracy: ${accuracy}% (${accurateEndpoints}/${checkedEndpoints} endpoints)\n`);
|
||||
|
||||
return { parameterIssues, accuracy, checkedEndpoints, accurateEndpoints };
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate quality assurance report
|
||||
*/
|
||||
function generateQAReport(hipaaViolations, authIssues, parameterValidation) {
|
||||
const report = {
|
||||
timestamp: new Date().toISOString(),
|
||||
summary: {
|
||||
hipaaCompliance: {
|
||||
status: hipaaViolations.length === 0 ? 'PASS' : 'NEEDS_ATTENTION',
|
||||
violations: hipaaViolations.length
|
||||
},
|
||||
authentication: {
|
||||
status: authIssues.length === 0 ? 'PASS' : 'NEEDS_ATTENTION',
|
||||
issues: authIssues.length
|
||||
},
|
||||
parameterAccuracy: {
|
||||
status: parameterValidation.accuracy >= 90 ? 'PASS' : 'NEEDS_IMPROVEMENT',
|
||||
accuracy: parameterValidation.accuracy + '%',
|
||||
checkedEndpoints: parameterValidation.checkedEndpoints,
|
||||
accurateEndpoints: parameterValidation.accurateEndpoints
|
||||
}
|
||||
},
|
||||
issues: {
|
||||
hipaaViolations,
|
||||
authIssues,
|
||||
parameterIssues: parameterValidation.parameterIssues
|
||||
},
|
||||
recommendations: []
|
||||
};
|
||||
|
||||
// Generate recommendations
|
||||
if (hipaaViolations.length > 0) {
|
||||
report.recommendations.push({
|
||||
priority: 'HIGH',
|
||||
category: 'HIPAA Compliance',
|
||||
action: `Review and recategorize ${hipaaViolations.length} endpoints that may violate HIPAA requirements`
|
||||
});
|
||||
}
|
||||
|
||||
if (authIssues.length > 0) {
|
||||
report.recommendations.push({
|
||||
priority: 'HIGH',
|
||||
category: 'Authentication',
|
||||
action: `Fix authentication requirements for ${authIssues.length} sensitive endpoints`
|
||||
});
|
||||
}
|
||||
|
||||
if (parameterValidation.accuracy < 90) {
|
||||
report.recommendations.push({
|
||||
priority: 'MEDIUM',
|
||||
category: 'Parameter Accuracy',
|
||||
action: `Improve parameter mapping accuracy from ${parameterValidation.accuracy}% to 90%+`
|
||||
});
|
||||
}
|
||||
|
||||
if (report.recommendations.length === 0) {
|
||||
report.recommendations.push({
|
||||
priority: 'LOW',
|
||||
category: 'Maintenance',
|
||||
action: 'All quality checks passed. Continue monitoring for compliance.'
|
||||
});
|
||||
}
|
||||
|
||||
return report;
|
||||
}
|
||||
|
||||
/**
|
||||
* Main validation function
|
||||
*/
|
||||
function performQualityAssurance() {
|
||||
console.log('🔍 Starting Quality Assurance Validation...\n');
|
||||
|
||||
// Load data
|
||||
const { apiDocs, endpointsContent } = loadData();
|
||||
console.log(`📊 Loaded ${apiDocs.length} API endpoints for validation\n`);
|
||||
|
||||
// Perform validations
|
||||
const hipaaViolations = validateHIPAACompliance(endpointsContent);
|
||||
const authIssues = validateAuthentication(endpointsContent);
|
||||
const parameterValidation = validateParameterAccuracy(apiDocs, endpointsContent);
|
||||
|
||||
// Generate report
|
||||
console.log('📋 Generating Quality Assurance Report...');
|
||||
const report = generateQAReport(hipaaViolations, authIssues, parameterValidation);
|
||||
|
||||
// Save report
|
||||
const reportPath = path.join(process.cwd(), 'quality-assurance-report.json');
|
||||
fs.writeFileSync(reportPath, JSON.stringify(report, null, 2));
|
||||
console.log(`✅ Report saved to: ${reportPath}\n`);
|
||||
|
||||
// Display summary
|
||||
console.log('📈 QUALITY ASSURANCE SUMMARY:');
|
||||
console.log(`HIPAA Compliance: ${report.summary.hipaaCompliance.status} (${report.summary.hipaaCompliance.violations} violations)`);
|
||||
console.log(`Authentication: ${report.summary.authentication.status} (${report.summary.authentication.issues} issues)`);
|
||||
console.log(`Parameter Accuracy: ${report.summary.parameterAccuracy.status} (${report.summary.parameterAccuracy.accuracy})`);
|
||||
|
||||
console.log('\n🎯 RECOMMENDATIONS:');
|
||||
report.recommendations.forEach(rec => {
|
||||
const icon = rec.priority === 'HIGH' ? '🔴' : rec.priority === 'MEDIUM' ? '🟡' : '🟢';
|
||||
console.log(`${icon} ${rec.action} (${rec.priority} priority)`);
|
||||
});
|
||||
|
||||
console.log('\n✅ Quality Assurance validation complete!');
|
||||
return report;
|
||||
}
|
||||
|
||||
// Run if called directly
|
||||
if (process.argv[1] && process.argv[1].endsWith('quality-assurance-validation.js')) {
|
||||
performQualityAssurance();
|
||||
}
|
||||
|
||||
export { performQualityAssurance };
|
Reference in New Issue
Block a user