#!/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 };