mcp-product-manager
Version:
MCP Orchestrator for task and project management with web interface
231 lines • 9.12 kB
JavaScript
// 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