UNPKG

mcp-product-manager

Version:

MCP Orchestrator for task and project management with web interface

231 lines 9.12 kB
// legacyAdapter.js - Legacy tool compatibility layer with deprecation warnings // Legacy endpoint mappings to new RBAC-compliant endpoints const LEGACY_MAPPINGS = { // Old task endpoints '/tasks/create': { new: '/api/tasks', method: 'POST', deprecated: '2025-08-01', replacement: 'Use POST /api/tasks with RBAC headers' }, '/tasks/list': { new: '/api/tasks/:project', method: 'GET', deprecated: '2025-08-01', replacement: 'Use GET /api/tasks/:project with project parameter' }, '/tasks/claim': { new: '/api/tasks/:id/claim', method: 'POST', deprecated: '2025-08-01', replacement: 'Use POST /api/tasks/:id/claim with RBAC role headers' }, // Old project endpoints '/projects/create': { new: '/api/projects', method: 'POST', deprecated: '2025-08-01', replacement: 'Use POST /api/projects with RBAC authentication' }, '/projects/list': { new: '/api/projects', method: 'GET', deprecated: '2025-08-01', replacement: 'Use GET /api/projects' }, // Old agent endpoints '/agents/spawn': { new: '/api/agents/spawn', method: 'POST', deprecated: '2025-08-01', replacement: 'Use POST /api/agents/spawn with ORCHESTRATOR role' }, // Old MCP endpoints '/mcp/execute': { new: '/api/mcp/execute', method: 'POST', deprecated: '2025-08-01', replacement: 'Use POST /api/mcp/execute with proper RBAC role' } }; // Deprecation warning levels const WARNING_LEVELS = { INFO: 'info', // First 30 days WARN: 'warn', // 30-60 days ERROR: 'error', // 60-90 days BLOCK: 'block' // After 90 days }; // Calculate warning level based on deprecation date const getWarningLevel = (deprecatedDate) => { const deprecated = new Date(deprecatedDate); const now = new Date(); const daysSinceDeprecation = Math.floor((now - deprecated) / (1000 * 60 * 60 * 24)); if (daysSinceDeprecation < 0) return WARNING_LEVELS.INFO; if (daysSinceDeprecation < 30) return WARNING_LEVELS.INFO; if (daysSinceDeprecation < 60) return WARNING_LEVELS.WARN; if (daysSinceDeprecation < 90) return WARNING_LEVELS.ERROR; return WARNING_LEVELS.BLOCK; }; // Generate deprecation warning message const generateDeprecationWarning = (oldPath, mapping, warningLevel) => { const baseMessage = `Legacy endpoint '${oldPath}' is deprecated as of ${mapping.deprecated}`; const replacementMessage = `Please migrate to: ${mapping.replacement}`; const messages = { [WARNING_LEVELS.INFO]: `ℹ️ ${baseMessage}. ${replacementMessage}`, [WARNING_LEVELS.WARN]: `⚠️ ${baseMessage}. ${replacementMessage}. Support will be removed soon.`, [WARNING_LEVELS.ERROR]: `🚨 ${baseMessage}. ${replacementMessage}. Support will be removed imminently.`, [WARNING_LEVELS.BLOCK]: `🛑 ${baseMessage}. This endpoint is no longer supported. ${replacementMessage}` }; return messages[warningLevel] || messages[WARNING_LEVELS.INFO]; }; // Legacy adapter middleware export const legacyAdapterMiddleware = (options = {}) => { const { enableDeprecationWarnings = true, blockDeprecatedEndpoints = process.env.NODE_ENV === 'production', logDeprecationUsage = true } = options; return (req, res, next) => { const originalPath = req.path; const mapping = LEGACY_MAPPINGS[originalPath]; // If not a legacy endpoint, continue normally if (!mapping) { return next(); } const warningLevel = getWarningLevel(mapping.deprecated); const warningMessage = generateDeprecationWarning(originalPath, mapping, warningLevel); // Log deprecation usage if (logDeprecationUsage) { const logEntry = { timestamp: new Date().toISOString(), legacy_endpoint: originalPath, replacement: mapping.new, warning_level: warningLevel, user_agent: req.headers['user-agent'], ip: req.ip, agent: req.headers['x-agent'] || req.body?.agent }; console.log(`[LEGACY] 📜 ${warningLevel.toUpperCase()}: ${originalPath}`, logEntry); } // Block deprecated endpoints if configured if (blockDeprecatedEndpoints && warningLevel === WARNING_LEVELS.BLOCK) { return res.status(410).json({ success: false, error: 'Endpoint no longer supported', details: { message: warningMessage, legacy_endpoint: originalPath, replacement: mapping.replacement, deprecated_since: mapping.deprecated, warning_level: warningLevel, migration_guide: 'See API documentation for RBAC migration steps' } }); } // Add deprecation headers if (enableDeprecationWarnings) { res.set({ 'X-API-Deprecated': 'true', 'X-API-Deprecation-Date': mapping.deprecated, 'X-API-Replacement': mapping.new, 'X-API-Warning-Level': warningLevel, 'X-API-Migration-Guide': 'https://docs.example.com/rbac-migration' }); } // Modify request to use new endpoint req.originalUrl = req.url; req.url = req.url.replace(originalPath, mapping.new); req.path = mapping.new; // Add legacy context to request req.legacy = { originalPath, newPath: mapping.new, warningLevel, deprecated: mapping.deprecated, isLegacyRequest: true }; // Add deprecation warning to response const originalSend = res.send; res.send = function (data) { // Parse response data to add warning let responseData; try { responseData = typeof data === 'string' ? JSON.parse(data) : data; } catch { responseData = data; } // Add deprecation warning to JSON responses if (typeof responseData === 'object' && responseData !== null) { responseData._deprecation = { warning: warningMessage, legacy_endpoint: originalPath, replacement: mapping.new, warning_level: warningLevel, deprecated_since: mapping.deprecated }; // Convert back to string if original was string if (typeof data === 'string') { data = JSON.stringify(responseData); } else { data = responseData; } } originalSend.call(res, data); }; next(); }; }; // Utility function to check if endpoint is deprecated export const isDeprecatedEndpoint = (path) => { return LEGACY_MAPPINGS.hasOwnProperty(path); }; // Get deprecation status for an endpoint export const getDeprecationStatus = (path) => { const mapping = LEGACY_MAPPINGS[path]; if (!mapping) { return null; } return { deprecated: true, deprecatedSince: mapping.deprecated, replacement: mapping.new, warningLevel: getWarningLevel(mapping.deprecated), blocked: getWarningLevel(mapping.deprecated) === WARNING_LEVELS.BLOCK }; }; // List all deprecated endpoints export const listDeprecatedEndpoints = () => { return Object.entries(LEGACY_MAPPINGS).map(([path, mapping]) => ({ path, replacement: mapping.new, method: mapping.method, deprecated: mapping.deprecated, warningLevel: getWarningLevel(mapping.deprecated), blocked: getWarningLevel(mapping.deprecated) === WARNING_LEVELS.BLOCK })); }; // Migration helper - generates migration report export const generateMigrationReport = () => { const endpoints = listDeprecatedEndpoints(); const report = { total_deprecated: endpoints.length, by_warning_level: { info: endpoints.filter(e => e.warningLevel === WARNING_LEVELS.INFO).length, warn: endpoints.filter(e => e.warningLevel === WARNING_LEVELS.WARN).length, error: endpoints.filter(e => e.warningLevel === WARNING_LEVELS.ERROR).length, blocked: endpoints.filter(e => e.warningLevel === WARNING_LEVELS.BLOCK).length }, endpoints, migration_notes: [ 'All new endpoints require RBAC authentication', 'Use X-Role header for role-based access control', 'Legacy endpoints will be removed in phases', 'See documentation for complete migration guide' ] }; return report; }; export default legacyAdapterMiddleware; //# sourceMappingURL=legacyAdapter.js.map